2
0

Cleanup, renaming restructuring, etc.

This commit is contained in:
Maarten Billemont
2017-05-07 18:36:01 -04:00
parent f86210f5da
commit fcbb93762a
62 changed files with 1599 additions and 1492 deletions

View File

@@ -23,12 +23,12 @@
@interface MPAnswersViewController()
@property(nonatomic, strong) NSManagedObjectID *siteOID;
@property(nonatomic) BOOL multiple;
@end
@implementation MPAnswersViewController {
NSManagedObjectID *_siteOID;
BOOL _multiple;
}
@implementation MPAnswersViewController
#pragma mark - Life
@@ -80,21 +80,21 @@
- (void)setSite:(MPSiteEntity *)site {
_siteOID = site.permanentObjectID;
_multiple = [site.questions count] > 0;
self.siteOID = site.permanentObjectID;
self.multiple = [site.questions count] > 0;
[self.tableView reloadData];
[self updateAnimated:NO];
}
- (void)setMultiple:(BOOL)multiple animated:(BOOL)animated {
_multiple = multiple;
self.multiple = multiple;
[self updateAnimated:animated];
}
- (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context {
return [MPSiteEntity existingObjectWithID:_siteOID inContext:context];
return [MPSiteEntity existingObjectWithID:self.siteOID inContext:context];
}
#pragma mark - UITableViewDelegate
@@ -109,7 +109,7 @@
if (section == 0)
return 3;
if (!_multiple)
if (!self.multiple)
return 0;
return [[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].questions count] + 1;
@@ -128,7 +128,7 @@
return [MPSendAnswersCell dequeueCellFromTableView:tableView indexPath:indexPath];
if (indexPath.item == 2) {
MPMultipleAnswersCell *cell = [MPMultipleAnswersCell dequeueCellFromTableView:tableView indexPath:indexPath];
cell.accessoryType = _multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;
cell.accessoryType = self.multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;
return cell;
}
Throw( @"Unsupported row index: %@", indexPath );
@@ -165,10 +165,10 @@
[self copyAnswer:((MPGlobalAnswersCell *)cell).answerField.text];
else if ([cell isKindOfClass:[MPMultipleAnswersCell class]]) {
if (!_multiple)
if (!self.multiple)
[self setMultiple:YES animated:YES];
else if (_multiple) {
else if (self.multiple) {
if (![site.questions count])
[self setMultiple:NO animated:YES];
@@ -194,7 +194,7 @@
else if ([cell isKindOfClass:[MPSendAnswersCell class]]) {
NSString *body;
if (!_multiple) {
if (!self.multiple) {
NSObject *answer = [site resolveSiteAnswerUsingKey:[MPiOSAppDelegate get].key];
body = strf( @"Master Password generated the following security answer for your site: %@\n\n"
@"%@\n"
@@ -245,7 +245,7 @@
PearlMainQueue( ^{
UITableViewCell *multipleAnswersCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:0]];
multipleAnswersCell.accessoryType = _multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;
multipleAnswersCell.accessoryType = self.multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
@@ -291,19 +291,23 @@
@end
@implementation MPAnswersQuestionCell {
NSManagedObjectID *_siteOID;
NSManagedObjectID *_questionOID;
__weak MPAnswersViewController *_answersVC;
}
@interface MPAnswersQuestionCell()
@property(nonatomic, strong) NSManagedObjectID *siteOID;
@property(nonatomic, strong) NSManagedObjectID *questionOID;
@property(nonatomic, weak) MPAnswersViewController *answersVC;
@end
@implementation MPAnswersQuestionCell
#pragma mark - State
- (void)setQuestion:(MPSiteQuestionEntity *)question forSite:(MPSiteEntity *)site inVC:(MPAnswersViewController *)answersVC {
_siteOID = site.permanentObjectID;
_questionOID = question.permanentObjectID;
_answersVC = answersVC;
self.siteOID = site.permanentObjectID;
self.questionOID = question.permanentObjectID;
self.answersVC = answersVC;
[self updateAnswerForQuestion:question ofSite:site];
}
@@ -322,8 +326,8 @@
NSString *keyword = textField.text;
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
BOOL didAddQuestionObject = NO;
MPSiteEntity *site = [MPSiteEntity existingObjectWithID:_siteOID inContext:context];
MPSiteQuestionEntity *question = [MPSiteQuestionEntity existingObjectWithID:_questionOID inContext:context];
MPSiteEntity *site = [MPSiteEntity existingObjectWithID:self.siteOID inContext:context];
MPSiteQuestionEntity *question = [MPSiteQuestionEntity existingObjectWithID:self.questionOID inContext:context];
if (!question) {
didAddQuestionObject = YES;
[site addQuestionsObject:question = [MPSiteQuestionEntity insertNewObjectInContext:context]];
@@ -333,11 +337,11 @@
question.keyword = keyword;
if ([context saveToStore]) {
_questionOID = question.permanentObjectID;
self.questionOID = question.permanentObjectID;
[self updateAnswerForQuestion:question ofSite:site];
if (didAddQuestionObject)
[_answersVC didAddQuestion:question toSite:site];
[self.answersVC didAddQuestion:question toSite:site];
}
}];
}

View File

@@ -19,8 +19,7 @@
#import "MPAppSettingsViewController.h"
#import "UIColor+Expanded.h"
@implementation MPAppSettingsViewController {
}
@implementation MPAppSettingsViewController
- (void)viewWillAppear:(BOOL)animated {

View File

@@ -32,11 +32,12 @@ const long MPAvatarAdd = 10000;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *avatarRaisedConstraint;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *keyboardHeightConstraint;
@property(nonatomic, strong) CAAnimationGroup *targetedShadowAnimation;
@property(assign, nonatomic, readwrite) BOOL newUser;
@end
@implementation MPAvatarCell {
CAAnimationGroup *_targetedShadowAnimation;
}
@implementation MPAvatarCell
+ (NSString *)reuseIdentifier {
@@ -57,14 +58,14 @@ const long MPAvatarAdd = 10000;
self.avatarImageView.layer.masksToBounds = NO;
self.avatarImageView.backgroundColor = [UIColor clearColor];
[self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *_self) {
_self.contentView.frame = _self.bounds;
[self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *self) {
self.contentView.frame = self.bounds;
}];
[self observeKeyPath:@"selected" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *_self) {
[_self updateAnimated:_self.superview != nil];
[self observeKeyPath:@"selected" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *self) {
[self updateAnimated:self.superview != nil];
}];
[self observeKeyPath:@"highlighted" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *_self) {
[_self updateAnimated:_self.superview != nil];
[self observeKeyPath:@"highlighted" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *self) {
[self updateAnimated:self.superview != nil];
}];
PearlAddNotificationObserver( UIKeyboardWillShowNotification, nil, [NSOperationQueue mainQueue],
^(MPAvatarCell *self, NSNotification *note) {
@@ -85,9 +86,9 @@ const long MPAvatarAdd = 10000;
pulseShadowOpacityAnimation.autoreverses = YES;
pulseShadowOpacityAnimation.repeatCount = MAXFLOAT;
_targetedShadowAnimation = [CAAnimationGroup new];
_targetedShadowAnimation.animations = @[ toShadowOpacityAnimation, pulseShadowOpacityAnimation ];
_targetedShadowAnimation.duration = MAXFLOAT;
self.targetedShadowAnimation = [CAAnimationGroup new];
self.targetedShadowAnimation.animations = @[ toShadowOpacityAnimation, pulseShadowOpacityAnimation ];
self.targetedShadowAnimation.duration = MAXFLOAT;
self.avatarImageView.layer.shadowColor = [UIColor whiteColor].CGColor;
self.avatarImageView.layer.shadowOffset = CGSizeZero;
}
@@ -96,10 +97,10 @@ const long MPAvatarAdd = 10000;
[super prepareForReuse];
_newUser = NO;
_visibility = 0;
_mode = MPAvatarModeLowered;
_spinnerActive = NO;
self.newUser = NO;
self.visibility = 0;
self.mode = MPAvatarModeLowered;
self.spinnerActive = NO;
}
- (void)dealloc {
@@ -114,13 +115,13 @@ const long MPAvatarAdd = 10000;
_avatar = avatar == MPAvatarAdd? MPAvatarAdd: (avatar + MPAvatarCount) % MPAvatarCount;
if (_avatar == MPAvatarAdd) {
if (self.avatar == MPAvatarAdd) {
self.avatarImageView.image = [UIImage imageNamed:@"avatar-add"];
self.name = strl( @"New User" );
_newUser = YES;
self.newUser = YES;
}
else
self.avatarImageView.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)_avatar )];
self.avatarImageView.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)self.avatar )];
}
- (NSString *)name {
@@ -140,7 +141,7 @@ const long MPAvatarAdd = 10000;
- (void)setVisibility:(CGFloat)visibility animated:(BOOL)animated {
if (visibility == _visibility)
if (self.visibility == visibility)
return;
_visibility = visibility;
@@ -161,7 +162,7 @@ const long MPAvatarAdd = 10000;
- (void)setMode:(MPAvatarMode)mode animated:(BOOL)animated {
if (mode == _mode)
if (self.mode == mode)
return;
_mode = mode;
@@ -175,7 +176,7 @@ const long MPAvatarAdd = 10000;
- (void)setSpinnerActive:(BOOL)spinnerActive animated:(BOOL)animated {
if (_spinnerActive == spinnerActive)
if (self.spinnerActive == spinnerActive)
return;
_spinnerActive = spinnerActive;
@@ -284,7 +285,7 @@ const long MPAvatarAdd = 10000;
if (self.mode == MPAvatarModeRaisedAndMinimized)
[self.avatarImageView.layer removeAnimationForKey:@"targetedShadow"];
else if (![self.avatarImageView.layer animationForKey:@"targetedShadow"])
[self.avatarImageView.layer addAnimation:_targetedShadowAnimation forKey:@"targetedShadow"];
[self.avatarImageView.layer addAnimation:self.targetedShadowAnimation forKey:@"targetedShadow"];
// Avatar selection and spinner.
if (self.mode != MPAvatarModeRaisedAndMinimized && (self.selected || self.highlighted) && !self.spinnerActive)

View File

@@ -18,7 +18,6 @@
#import "MPCell.h"
@implementation MPCell {
}
@implementation MPCell
@end

View File

@@ -18,17 +18,23 @@
#import "MPCoachmarkViewController.h"
@implementation MPCoachmarkViewController {
NSArray *_views;
NSUInteger _nextView;
__weak NSTimer *_viewTimer;
}
@interface MPCoachmarkViewController()
@property(nonatomic, strong) NSArray *views;
@property(nonatomic) NSUInteger nextView;
@property(nonatomic, weak) NSTimer *viewTimer;
@end
@implementation MPCoachmarkViewController
- (void)viewDidLoad {
[super viewDidLoad];
_views = @[ self.view0, self.view1, self.view2, self.view3, self.view4, self.view5, self.view6, self.view7, self.view8, self.view9 ];
self.views = @[
self.view0, self.view1, self.view2, self.view3, self.view4, self.view5, self.view6, self.view7, self.view8, self.view9
];
}
- (void)viewWillAppear:(BOOL)animated {
@@ -37,8 +43,8 @@
self.viewProgress.visible = YES;
self.viewProgress.progress = 0;
[_views makeObjectsPerformSelector:@selector( setVisible: ) withObject:@NO];
_nextView = 0;
[self.views makeObjectsPerformSelector:@selector( setVisible: ) withObject:@NO];
self.nextView = 0;
}
- (void)viewDidAppear:(BOOL)animated {
@@ -46,23 +52,23 @@
[super viewDidAppear:animated];
[UIView animateWithDuration:0.3f animations:^{
[_views[_nextView++] setVisible:YES];
[self.views[self.nextView++] setVisible:YES];
}];
_viewTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimer *timer) {
self.viewTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimer *timer) {
self.viewProgress.progress += 1.0f / 50;
if (self.viewProgress.progress == 1)
[UIView animateWithDuration:0.3f animations:^{
self.viewProgress.progress = 0;
[_views[_nextView++] setVisible:YES];
[self.views[self.nextView++] setVisible:YES];
if (_nextView >= [_views count]) {
[_viewTimer invalidate];
if (self.nextView >= [self.views count]) {
[self.viewTimer invalidate];
self.viewProgress.visible = NO;
}
}];
} repeats:YES];
} repeats:YES];
}
- (UIStatusBarStyle)preferredStatusBarStyle {

View File

@@ -17,7 +17,7 @@
//==============================================================================
#import "MPUsersViewController.h"
#import "MPPasswordsViewController.h"
#import "MPSitesViewController.h"
#import "MPEmergencyViewController.h"
typedef NS_ENUM( NSUInteger, MPCombinedMode ) {
@@ -29,7 +29,7 @@ typedef NS_ENUM( NSUInteger, MPCombinedMode ) {
@property(nonatomic) MPCombinedMode mode;
@property(nonatomic, weak) MPUsersViewController *usersVC;
@property(nonatomic, weak) MPPasswordsViewController *passwordsVC;
@property(nonatomic, weak) MPSitesViewController *sitesVC;
@property(nonatomic, weak) MPEmergencyViewController *emergencyVC;
@end

View File

@@ -18,9 +18,9 @@
#import "MPCombinedViewController.h"
#import "MPUsersViewController.h"
#import "MPPasswordsViewController.h"
#import "MPSitesViewController.h"
#import "MPEmergencyViewController.h"
#import "MPPasswordsSegue.h"
#import "MPSitesSegue.h"
@implementation MPCombinedViewController
@@ -30,7 +30,7 @@
[super viewDidLoad];
_mode = MPCombinedModeUserSelection;
self.mode = MPCombinedModeUserSelection;
[self performSegueWithIdentifier:@"users" sender:self];
}
@@ -67,12 +67,12 @@
if ([segue.identifier isEqualToString:@"users"])
self.usersVC = segue.destinationViewController;
if ([segue.identifier isEqualToString:@"passwords"]) {
NSAssert( [segue isKindOfClass:[MPPasswordsSegue class]], @"passwords segue should be MPPasswordsSegue: %@", segue );
NSAssert( [segue isKindOfClass:[MPSitesSegue class]], @"passwords segue should be MPSitesSegue: %@", segue );
NSAssert( [sender isKindOfClass:[NSDictionary class]], @"sender should be dictionary: %@", sender );
NSAssert( [[sender objectForKey:@"animated"] isKindOfClass:[NSNumber class]], @"sender should contain 'animated': %@", sender );
[(MPPasswordsSegue *)segue setAnimated:[sender[@"animated"] boolValue]];
[(MPSitesSegue *)segue setAnimated:[sender[@"animated"] boolValue]];
UIViewController *destinationVC = segue.destinationViewController;
_passwordsVC = [destinationVC isKindOfClass:[MPPasswordsViewController class]]? (MPPasswordsViewController *)destinationVC: nil;
self.sitesVC = [destinationVC isKindOfClass:[MPSitesViewController class]]? (MPSitesViewController *)destinationVC: nil;
}
if ([segue.identifier isEqualToString:@"emergency"])
self.emergencyVC = segue.destinationViewController;
@@ -115,7 +115,7 @@
- (void)setMode:(MPCombinedMode)mode animated:(BOOL)animated {
if (_mode == mode && animated)
if (self.mode == mode && animated)
return;
_mode = mode;
@@ -129,8 +129,8 @@
case MPCombinedModeUserSelection: {
self.usersVC.view.userInteractionEnabled = YES;
[self.usersVC setActive:YES animated:animated];
if (_passwordsVC) {
MPPasswordsSegue *segue = [[MPPasswordsSegue alloc] initWithIdentifier:@"passwords" source:_passwordsVC destination:self];
if (self.sitesVC) {
MPSitesSegue *segue = [[MPSitesSegue alloc] initWithIdentifier:@"passwords" source:self.sitesVC destination:self];
[self prepareForSegue:segue sender:@{ @"animated": @(animated) }];
[segue perform];
}

View File

@@ -19,18 +19,22 @@
#import "MPEmergencyViewController.h"
#import "MPEntities.h"
@implementation MPEmergencyViewController {
MPKey *_key;
NSOperationQueue *_emergencyKeyQueue;
NSOperationQueue *_emergencyPasswordQueue;
}
@interface MPEmergencyViewController()
@property(nonatomic, strong) MPKey *key;
@property(nonatomic, strong) NSOperationQueue *emergencyKeyQueue;
@property(nonatomic, strong) NSOperationQueue *emergencyPasswordQueue;
@end
@implementation MPEmergencyViewController
- (void)viewDidLoad {
[super viewDidLoad];
[_emergencyKeyQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1];
[_emergencyPasswordQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1];
[self.emergencyKeyQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1];
[self.emergencyPasswordQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1];
self.view.backgroundColor = [UIColor clearColor];
self.dialogView.layer.cornerRadius = 5;
@@ -117,12 +121,12 @@
[self.passwordButton setTitle:nil forState:UIControlStateNormal];
[self.activity startAnimating];
[_emergencyKeyQueue cancelAllOperations];
[_emergencyKeyQueue addOperationWithBlock:^{
[self.emergencyKeyQueue cancelAllOperations];
[self.emergencyKeyQueue addOperationWithBlock:^{
if ([masterPassword length] && [fullName length])
_key = [[MPKey alloc] initForFullName:fullName withMasterPassword:masterPassword];
self.key = [[MPKey alloc] initForFullName:fullName withMasterPassword:masterPassword];
else
_key = nil;
self.key = nil;
PearlMainQueue( ^{
[self updatePassword];
@@ -139,11 +143,12 @@
[self.passwordButton setTitle:nil forState:UIControlStateNormal];
[self.activity startAnimating];
[_emergencyPasswordQueue cancelAllOperations];
[_emergencyPasswordQueue addOperationWithBlock:^{
[self.emergencyPasswordQueue cancelAllOperations];
[self.emergencyPasswordQueue addOperationWithBlock:^{
NSString *sitePassword = nil;
if (_key && [siteName length])
sitePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:siteName ofType:siteType withCounter:siteCounter usingKey:_key];
if (self.key && [siteName length])
sitePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:siteName ofType:siteType withCounter:siteCounter
usingKey:self.key];
PearlMainQueue( ^{
[self.activity stopAnimating];

View File

@@ -18,15 +18,19 @@
#import "MPOverlayViewController.h"
@implementation MPOverlayViewController {
NSMutableDictionary *_dismissSegueByButton;
}
@interface MPOverlayViewController()
@property(nonatomic, strong) NSMutableDictionary *dismissSegueByButton;
@end
@implementation MPOverlayViewController
- (void)awakeFromNib {
[super awakeFromNib];
_dismissSegueByButton = [NSMutableDictionary dictionary];
self.dismissSegueByButton = [NSMutableDictionary dictionary];
}
- (void)viewDidLoad {
@@ -60,7 +64,7 @@
dismissButton.visible = NO;
dismissButton.frame = self.view.bounds;
dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] =
self.dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] =
[[MPOverlaySegue alloc] initWithIdentifier:@"dismiss-overlay"
source:segue.destinationViewController destination:segue.sourceViewController];
@@ -71,14 +75,14 @@
- (void)dismissOverlay:(UIButton *)dismissButton {
NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton];
[((UIStoryboardSegue *)_dismissSegueByButton[dismissSegueKey]) perform];
[((UIStoryboardSegue *)self.dismissSegueByButton[dismissSegueKey]) perform];
}
- (void)removeDismissButtonForViewController:(UIViewController *)viewController {
UIButton *dismissButton = nil;
for (NSValue *dismissButtonValue in [_dismissSegueByButton allKeys])
if (((UIStoryboardSegue *)_dismissSegueByButton[dismissButtonValue]).sourceViewController == viewController) {
for (NSValue *dismissButtonValue in [self.dismissSegueByButton allKeys])
if (((UIStoryboardSegue *)self.dismissSegueByButton[dismissButtonValue]).sourceViewController == viewController) {
dismissButton = [dismissButtonValue nonretainedObjectValue];
NSAssert( [self.view.subviews containsObject:dismissButton], @"Missing dismiss button in dictionary." );
}
@@ -86,7 +90,7 @@
return;
NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton];
[_dismissSegueByButton removeObjectForKey:dismissSegueKey];
[self.dismissSegueByButton removeObjectForKey:dismissSegueKey];
[UIView animateWithDuration:0.1f animations:^{
dismissButton.visible = NO;

View File

@@ -17,16 +17,15 @@
//==============================================================================
#import "MPPopdownSegue.h"
#import "MPPasswordsViewController.h"
#import "MPSitesViewController.h"
@implementation MPPopdownSegue {
}
@implementation MPPopdownSegue
- (void)perform {
MPPasswordsViewController *passwordsVC;
MPSitesViewController *passwordsVC;
UIViewController *popdownVC;
if ([self.sourceViewController isKindOfClass:[MPPasswordsViewController class]]) {
if ([self.sourceViewController isKindOfClass:[MPSitesViewController class]]) {
passwordsVC = self.sourceViewController;
popdownVC = self.destinationViewController;
UIView *popdownView = popdownVC.view;
@@ -55,7 +54,7 @@
}
else {
popdownVC = self.sourceViewController;
for (passwordsVC = self.sourceViewController; passwordsVC && ![(id)passwordsVC isKindOfClass:[MPPasswordsViewController class]];
for (passwordsVC = self.sourceViewController; passwordsVC && ![(id)passwordsVC isKindOfClass:[MPSitesViewController class]];
passwordsVC = (id)passwordsVC.parentViewController);
NSAssert( passwordsVC, @"Couldn't find passwords VC to pop back to." );

View File

@@ -32,7 +32,7 @@
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated1TypeControl;
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated2TypeControl;
@property(weak, nonatomic) IBOutlet UISegmentedControl *storedTypeControl;
@property(weak, nonatomic) IBOutlet UILabel *passwordTypeExample;
@property(weak, nonatomic) IBOutlet UILabel *typeSamplePassword;
- (IBAction)previousAvatar:(id)sender;
- (IBAction)nextAvatar:(id)sender;

View File

@@ -21,7 +21,7 @@
#import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h"
#import "UIColor+Expanded.h"
#import "MPPasswordsViewController.h"
#import "MPSitesViewController.h"
#import "MPAppDelegate_InApp.h"
@interface MPPreferencesViewController()
@@ -70,7 +70,7 @@
examplePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:@"test" ofType:defaultType
withCounter:1 usingKey:[MPiOSAppDelegate get].key];
PearlMainQueue( ^{
self.passwordTypeExample.text = [examplePassword length]? [NSString stringWithFormat:@"eg. %@", examplePassword]: nil;
self.typeSamplePassword.text = [examplePassword length]? [NSString stringWithFormat:@"eg. %@", examplePassword]: nil;
} );
} );
}
@@ -108,7 +108,7 @@
[[MPiOSAppDelegate get] showExportForVC:self];
if (cell == self.showHelpCell) {
MPPasswordsViewController *passwordsVC = [self dismissPopup];
MPSitesViewController *passwordsVC = [self dismissPopup];
[passwordsVC performSegueWithIdentifier:@"guide" sender:self];
}
@@ -230,11 +230,11 @@
#pragma mark - Private
- (MPPasswordsViewController *)dismissPopup {
- (MPSitesViewController *)dismissPopup {
for (UIViewController *vc = self; (vc = vc.parentViewController);)
if ([vc isKindOfClass:[MPPasswordsViewController class]]) {
MPPasswordsViewController *passwordsVC = (MPPasswordsViewController *)vc;
if ([vc isKindOfClass:[MPSitesViewController class]]) {
MPSitesViewController *passwordsVC = (MPSitesViewController *)vc;
[passwordsVC dismissPopdown:self];
return passwordsVC;
}
@@ -254,32 +254,32 @@
case 1:
return MPSiteTypeGeneratedName;
default:
switch (selectedGenerated2Index) {
case 0:
return MPSiteTypeGeneratedMaximum;
case 1:
return MPSiteTypeGeneratedLong;
case 2:
return MPSiteTypeGeneratedMedium;
case 3:
return MPSiteTypeGeneratedBasic;
case 4:
return MPSiteTypeGeneratedShort;
case 5:
return MPSiteTypeGeneratedPIN;
default:
switch (selectedStoredIndex) {
switch (selectedGenerated2Index) {
case 0:
return MPSiteTypeStoredPersonal;
return MPSiteTypeGeneratedMaximum;
case 1:
return MPSiteTypeStoredDevicePrivate;
return MPSiteTypeGeneratedLong;
case 2:
return MPSiteTypeGeneratedMedium;
case 3:
return MPSiteTypeGeneratedBasic;
case 4:
return MPSiteTypeGeneratedShort;
case 5:
return MPSiteTypeGeneratedPIN;
default:
Throw( @"unsupported selected type index: generated1=%ld, generated2=%ld, stored=%ld",
(long)selectedGenerated1Index, (long)selectedGenerated2Index, (long)selectedStoredIndex );
switch (selectedStoredIndex) {
case 0:
return MPSiteTypeStoredPersonal;
case 1:
return MPSiteTypeStoredDevicePrivate;
default:
Throw( @"unsupported selected type index: generated1=%ld, generated2=%ld, stored=%ld",
(long)selectedGenerated1Index, (long)selectedGenerated2Index, (long)selectedStoredIndex );
}
}
}
}
}
- (NSInteger)generated1SegmentIndexForType:(MPSiteType)type {

View File

@@ -18,8 +18,7 @@
#import "MPRootSegue.h"
@implementation MPRootSegue {
}
@implementation MPRootSegue
- (void)perform {

View File

@@ -20,18 +20,18 @@
#import "MPEntities.h"
#import "MPCell.h"
typedef NS_ENUM ( NSUInteger, MPPasswordCellMode ) {
typedef NS_ENUM ( NSUInteger, MPSiteCellMode ) {
MPPasswordCellModePassword,
MPPasswordCellModeSettings,
};
@interface MPPasswordCell : MPCell<UIScrollViewDelegate, UITextFieldDelegate>
@interface MPSiteCell : MPCell<UIScrollViewDelegate, UITextFieldDelegate>
@property(nonatomic) NSArray *fuzzyGroups;
- (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated;
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated;
- (void)setMode:(MPSiteCellMode)mode animated:(BOOL)animated;
- (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context;
@end

View File

@@ -16,13 +16,12 @@
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPPasswordCell.h"
#import "MPSiteCell.h"
#import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Store.h"
#import "UIColor+Expanded.h"
#import "MPAppDelegate_InApp.h"
@interface MPPasswordCell()
@interface MPSiteCell()
@property(nonatomic, strong) IBOutlet UILabel *siteNameLabel;
@property(nonatomic, strong) IBOutlet UITextField *passwordField;
@@ -41,14 +40,13 @@
@property(nonatomic, strong) IBOutlet UIButton *loginNameButton;
@property(nonatomic, strong) IBOutlet UIView *indicatorView;
@property(nonatomic) MPPasswordCellMode mode;
@property(nonatomic) MPSiteCellMode mode;
@property(nonatomic, copy) NSString *transientSite;
@property(nonatomic, strong) NSManagedObjectID *siteOID;
@end
@implementation MPPasswordCell {
NSManagedObjectID *_siteOID;
}
@implementation MPSiteCell
#pragma mark - Life cycle
@@ -65,9 +63,9 @@
[self setupLayer];
[self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPPasswordCell *_self) {
[self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPSiteCell *self) {
if (from && !CGSizeEqualToSize( [from CGRectValue].size, [to CGRectValue].size ))
[_self setupLayer];
[self setupLayer];
}];
[self.contentButton observeKeyPath:@"highlighted"
withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) {
@@ -135,8 +133,8 @@
[super prepareForReuse];
_siteOID = nil;
_fuzzyGroups = nil;
self.siteOID = nil;
self.fuzzyGroups = nil;
self.transientSite = nil;
self.mode = MPPasswordCellModePassword;
[self updateAnimated:NO];
@@ -153,25 +151,25 @@
- (void)setFuzzyGroups:(NSArray *)fuzzyGroups {
if (_fuzzyGroups == fuzzyGroups)
if (self.fuzzyGroups == fuzzyGroups)
return;
_fuzzyGroups = fuzzyGroups;
[self updateSiteName:[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]];
}
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated {
- (void)setMode:(MPSiteCellMode)mode animated:(BOOL)animated {
if (mode == _mode)
if (self.mode == mode)
return;
_mode = mode;
[self updateAnimated:animated];
}
- (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated {
_siteOID = site.permanentObjectID;
self.siteOID = site.permanentObjectID;
[self updateAnimated:animated];
}
@@ -368,7 +366,7 @@
}
- (IBAction)doAction:(UIButton *)sender {
[MPiOSAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *mainContext) {
MPSiteEntity *mainSite = [self siteInContext:mainContext];
[PearlAlert showAlertWithTitle:@"Login Page" message:nil
@@ -531,7 +529,7 @@
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
// UI
self.backgroundColor = mainSite.url? [UIColor greenColor]: [UIColor redColor];
//self.backgroundColor = mainSite.url? [UIColor greenColor]: [UIColor redColor];
self.upgradeButton.gone = !mainSite.requiresExplicitMigration && ![[MPiOSConfig get].allowDowngrade boolValue];
self.answersButton.gone = ![[MPiOSAppDelegate get] isFeatureUnlocked:MPProductGenerateAnswers];
BOOL settingsMode = self.mode == MPPasswordCellModeSettings;
@@ -678,7 +676,7 @@
[self.window endEditing:YES];
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
if ([pasteboard respondsToSelector:@selector(setItems:options:)]) {
if ([pasteboard respondsToSelector:@selector( setItems:options: )]) {
[pasteboard setItems:@[ @{ UIPasteboardTypeAutomatic: password } ]
options:@{
UIPasteboardOptionLocalOnly : @NO,
@@ -718,7 +716,7 @@
- (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context {
return [MPSiteEntity existingObjectWithID:_siteOID inContext:context];
return [MPSiteEntity existingObjectWithID:self.siteOID inContext:context];
}
@end

View File

@@ -18,7 +18,7 @@
#import <Foundation/Foundation.h>
@interface MPPasswordsSegue : UIStoryboardSegue
@interface MPSitesSegue : UIStoryboardSegue
@property(nonatomic, assign) BOOL animated;

View File

@@ -16,12 +16,11 @@
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPPasswordsSegue.h"
#import "MPPasswordsViewController.h"
#import "MPSitesSegue.h"
#import "MPSitesViewController.h"
#import "MPCombinedViewController.h"
@implementation MPPasswordsSegue {
}
@implementation MPSitesSegue
- (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination {
@@ -35,34 +34,34 @@
- (void)perform {
if ([self.destinationViewController isKindOfClass:[MPPasswordsViewController class]]) {
__weak MPPasswordsViewController *passwordsVC = self.destinationViewController;
if ([self.destinationViewController isKindOfClass:[MPSitesViewController class]]) {
__weak MPSitesViewController *sitesVC = self.destinationViewController;
MPCombinedViewController *combinedVC = self.sourceViewController;
[combinedVC addChildViewController:passwordsVC];
passwordsVC.active = NO;
[combinedVC addChildViewController:sitesVC];
sitesVC.active = NO;
UIView *passwordsView = passwordsVC.view;
passwordsView.frame = combinedVC.view.bounds;
passwordsView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[combinedVC.view insertSubview:passwordsView belowSubview:combinedVC.usersVC.view];
UIView *sitesView = sitesVC.view;
sitesView.frame = combinedVC.view.bounds;
sitesView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[combinedVC.view insertSubview:sitesView belowSubview:combinedVC.usersVC.view];
[passwordsVC setActive:YES animated:self.animated completion:^(BOOL finished) {
[sitesVC setActive:YES animated:self.animated completion:^(BOOL finished) {
if (!finished)
return;
[passwordsVC didMoveToParentViewController:combinedVC];
[sitesVC didMoveToParentViewController:combinedVC];
}];
}
else if ([self.sourceViewController isKindOfClass:[MPPasswordsViewController class]]) {
__weak MPPasswordsViewController *passwordsVC = self.sourceViewController;
else if ([self.sourceViewController isKindOfClass:[MPSitesViewController class]]) {
__weak MPSitesViewController *sitesVC = self.sourceViewController;
[passwordsVC willMoveToParentViewController:nil];
[passwordsVC setActive:NO animated:self.animated completion:^(BOOL finished) {
[sitesVC willMoveToParentViewController:nil];
[sitesVC setActive:NO animated:self.animated completion:^(BOOL finished) {
if (!finished)
return;
[passwordsVC.view removeFromSuperview];
[passwordsVC removeFromParentViewController];
[sitesVC.view removeFromSuperview];
[sitesVC removeFromParentViewController];
}];
}
}

View File

@@ -19,22 +19,22 @@
@class MPSiteEntity;
@class MPCoachmark;
@interface MPPasswordsViewController : UIViewController<UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@interface MPSitesViewController : UIViewController<UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property(strong, nonatomic) IBOutlet UIView *passwordSelectionContainer;
@property(strong, nonatomic) IBOutlet UICollectionView *passwordCollectionView;
@property(strong, nonatomic) IBOutlet UISearchBar *passwordsSearchBar;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *passwordsToBottomConstraint;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *navigationBarToTopConstraint;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *popdownToTopConstraint;
@property(strong, nonatomic) IBOutlet UIView *badNameTipContainer;
@property(strong, nonatomic) IBOutlet UIView *popdownView;
@property(strong, nonatomic) IBOutlet UIView *popdownContainer;
@property(nonatomic, strong) IBOutlet UICollectionView *collectionView;
@property(nonatomic, strong) IBOutlet UINavigationBar *navigationBar;
@property(nonatomic, strong) IBOutlet UISearchBar *searchBar;
@property(nonatomic, strong) IBOutlet NSLayoutConstraint *sitesToBottomConstraint;
@property(nonatomic, strong) IBOutlet NSLayoutConstraint *navigationBarToTopConstraint;
@property(nonatomic, strong) IBOutlet NSLayoutConstraint *popdownToTopConstraint;
@property(nonatomic, strong) IBOutlet UIView *badNameTipContainer;
@property(nonatomic, strong) IBOutlet UIView *popdownView;
@property(nonatomic, strong) IBOutlet UIView *popdownContainer;
@property(assign, nonatomic) BOOL active;
- (void)setActive:(BOOL)active animated:(BOOL)animated completion:(void ( ^ )(BOOL finished))completion;
- (void)reloadPasswords;
- (void)reloadSites;
- (IBAction)dismissPopdown:(id)sender;

View File

@@ -16,12 +16,12 @@
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPPasswordsViewController.h"
#import "MPSitesViewController.h"
#import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Store.h"
#import "MPPopdownSegue.h"
#import "MPAppDelegate_Key.h"
#import "MPPasswordCell.h"
#import "MPSiteCell.h"
#import "MPAnswersViewController.h"
#import "MPMessageViewController.h"
@@ -31,22 +31,17 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
MPPasswordsBadNameTip = 1 << 0,
};
@interface MPPasswordsViewController()<NSFetchedResultsControllerDelegate>
@interface MPSitesViewController()<NSFetchedResultsControllerDelegate>
@property(nonatomic, strong) IBOutlet UINavigationBar *navigationBar;
@property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@property(nonatomic, strong) NSArray *fuzzyGroups;
@property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet;
@property(nonatomic, strong) NSMutableArray<NSMutableArray *> *dataSource;
@property(nonatomic, weak) UIViewController *popdownVC;
@end
@implementation MPPasswordsViewController {
__weak UITapGestureRecognizer *_passwordsDismissRecognizer;
NSFetchedResultsController *_fetchedResultsController;
UIColor *_backgroundColor;
UIColor *_darkenedBackgroundColor;
__weak UIViewController *_popdownVC;
NSCharacterSet *_siteNameAcceptableCharactersSet;
NSArray *_fuzzyGroups;
NSMutableArray<NSMutableArray *> *_passwordCollectionSections;
}
@implementation MPSitesViewController
#pragma mark - Life
@@ -57,22 +52,20 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
NSMutableCharacterSet *siteNameAcceptableCharactersSet = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[siteNameAcceptableCharactersSet formIntersectionWithCharacterSet:[[NSCharacterSet uppercaseLetterCharacterSet] invertedSet]];
[siteNameAcceptableCharactersSet addCharactersInString:@"@.-+~&_;:/"];
_siteNameAcceptableCharactersSet = siteNameAcceptableCharactersSet;
self.siteNameAcceptableCharactersSet = siteNameAcceptableCharactersSet;
_backgroundColor = self.passwordCollectionView.backgroundColor;
_darkenedBackgroundColor = [_backgroundColor colorWithAlphaComponent:0.6f];
_passwordCollectionSections = [NSMutableArray new];
self.dataSource = [NSMutableArray new];
self.view.backgroundColor = [UIColor clearColor];
[self.passwordCollectionView automaticallyAdjustInsetsForKeyboard];
self.passwordsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
if ([self.passwordsSearchBar respondsToSelector:@selector( keyboardAppearance )])
self.passwordsSearchBar.keyboardAppearance = UIKeyboardAppearanceDark;
[self.collectionView automaticallyAdjustInsetsForKeyboard];
self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
if ([self.searchBar respondsToSelector:@selector( keyboardAppearance )])
self.searchBar.keyboardAppearance = UIKeyboardAppearanceDark;
else
[self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
[self.searchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
if ([subview isKindOfClass:[UITextField class]])
((UITextField *)subview).keyboardAppearance = UIKeyboardAppearanceDark;
} recurse:YES];
} recurse:YES];
}
- (void)viewWillAppear:(BOOL)animated {
@@ -98,7 +91,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
if (pasteboardURL.host)
self.query = NSNullToNil( [pasteboardURL.host firstMatchGroupsOfExpression:bareHostRE][0] );
else
[self reloadPasswords];
[self reloadSites];
}
- (void)viewDidAppear:(BOOL)animated {
@@ -131,17 +124,17 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"popdown"])
_popdownVC = segue.destinationViewController;
self.popdownVC = segue.destinationViewController;
if ([segue.identifier isEqualToString:@"answers"])
((MPAnswersViewController *)segue.destinationViewController).site =
[[MPPasswordCell findAsSuperviewOf:sender] siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
[[MPSiteCell findAsSuperviewOf:sender] siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
if ([segue.identifier isEqualToString:@"message"])
((MPMessageViewController *)segue.destinationViewController).message = sender;
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[self.passwordCollectionView.collectionViewLayout invalidateLayout];
[self.collectionView.collectionViewLayout invalidateLayout];
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
@@ -159,7 +152,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
insetForSectionAtIndex:(NSInteger)section {
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout;
UIEdgeInsets occludedInsets = [self.passwordCollectionView occludedInsets];
UIEdgeInsets occludedInsets = [self.collectionView occludedInsets];
UIEdgeInsets insets = layout.sectionInset;
insets.top = insets.bottom; // Undo storyboard hack for manual top-occluded insets.
@@ -176,19 +169,19 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return [_passwordCollectionSections count];
return [self.dataSource count];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [_passwordCollectionSections[(NSUInteger)section] count];
return [self.dataSource[(NSUInteger)section] count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MPPasswordCell *cell = [MPPasswordCell dequeueCellFromCollectionView:collectionView indexPath:indexPath];
[cell setFuzzyGroups:_fuzzyGroups];
id item = _passwordCollectionSections[(NSUInteger)indexPath.section][(NSUInteger)indexPath.item];
MPSiteCell *cell = [MPSiteCell dequeueCellFromCollectionView:collectionView indexPath:indexPath];
[cell setFuzzyGroups:self.fuzzyGroups];
id item = self.dataSource[(NSUInteger)indexPath.section][(NSUInteger)indexPath.item];
if ([item isKindOfClass:[MPSiteEntity class]])
[cell setSite:item animated:NO];
else // item == MPTransientPasswordItem
@@ -201,8 +194,8 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if (scrollView == self.passwordCollectionView)
for (MPPasswordCell *cell in [self.passwordCollectionView visibleCells])
if (scrollView == self.collectionView)
for (MPSiteCell *cell in [self.collectionView visibleCells])
[cell setMode:MPPasswordCellModePassword animated:YES];
}
@@ -210,11 +203,11 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
if (controller == _fetchedResultsController)
if (controller == self.fetchedResultsController)
PearlMainQueue( ^{
[self.passwordCollectionView updateDataSource:_passwordCollectionSections
toSections:[self createPasswordCollectionSections]
reloadItems:nil completion:nil];
[self.collectionView updateDataSource:self.dataSource
toSections:[self createPasswordCollectionSections]
reloadItems:nil completion:nil];
} );
}
@@ -222,7 +215,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
if (searchBar == self.passwordsSearchBar) {
if (searchBar == self.searchBar) {
searchBar.text = nil;
return YES;
}
@@ -232,24 +225,22 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
if (searchBar == self.passwordsSearchBar) {
[self.passwordsSearchBar setShowsCancelButton:YES animated:YES];
if (searchBar == self.searchBar) {
[self.searchBar setShowsCancelButton:YES animated:YES];
[UIView animateWithDuration:0.3f animations:^{
self.passwordCollectionView.backgroundColor = _darkenedBackgroundColor;
self.collectionView.backgroundColor = [self.collectionView.backgroundColor colorWithAlphaComponent:0.6f];
}];
}
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
if (searchBar == self.passwordsSearchBar) {
[self.passwordsSearchBar setShowsCancelButton:NO animated:YES];
if (_passwordsDismissRecognizer)
[self.view removeGestureRecognizer:_passwordsDismissRecognizer];
if (searchBar == self.searchBar) {
[self.searchBar setShowsCancelButton:NO animated:YES];
[self reloadSites];
[self reloadPasswords];
[UIView animateWithDuration:0.3f animations:^{
self.passwordCollectionView.backgroundColor = _backgroundColor;
self.collectionView.backgroundColor = [self.collectionView.backgroundColor colorWithAlphaComponent:0];
}];
}
}
@@ -267,11 +258,11 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchBar == self.passwordsSearchBar) {
if ([[self.query stringByTrimmingCharactersInSet:_siteNameAcceptableCharactersSet] length])
if (searchBar == self.searchBar) {
if ([[self.query stringByTrimmingCharactersInSet:self.siteNameAcceptableCharactersSet] length])
[self showTips:MPPasswordsBadNameTip];
[self reloadPasswords];
[self reloadSites];
}
}
@@ -321,42 +312,42 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
PearlRemoveNotificationObservers();
PearlAddNotificationObserver( UIApplicationWillResignActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
^(MPSitesViewController *self, NSNotification *note) {
[self.view endEditing:YES];
self.passwordSelectionContainer.visible = NO;
self.view.visible = NO;
} );
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
^(MPSitesViewController *self, NSNotification *note) {
[UIView animateWithDuration:0.7f animations:^{
self.passwordSelectionContainer.visible = YES;
self.view.visible = YES;
}];
} );
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
^(MPSitesViewController *self, NSNotification *note) {
[self viewWillAppear:YES];
} );
PearlAddNotificationObserver( MPSignedOutNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
^(MPSitesViewController *self, NSNotification *note) {
PearlMainQueue( ^{
self->_fetchedResultsController = nil;
self.fetchedResultsController = nil;
self.query = nil;
} );
} );
PearlAddNotificationObserver( MPCheckConfigNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
^(MPSitesViewController *self, NSNotification *note) {
PearlMainQueue( ^{
[self updateConfigKey:note.object];
} );
} );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
self->_fetchedResultsController = nil;
[self reloadPasswords];
^(MPSitesViewController *self, NSNotification *note) {
self.fetchedResultsController = nil;
[self reloadSites];
} );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
^(MPSitesViewController *self, NSNotification *note) {
PearlMainQueue( ^{
[self reloadPasswords];
[self reloadSites];
[self registerObservers];
} );
} );
@@ -373,12 +364,12 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)updateConfigKey:(NSString *)key {
if (!key || [key isEqualToString:NSStringFromSelector( @selector( dictationSearch ) )])
self.passwordsSearchBar.keyboardType = [[MPiOSConfig get].dictationSearch boolValue]? UIKeyboardTypeDefault: UIKeyboardTypeURL;
self.searchBar.keyboardType = [[MPiOSConfig get].dictationSearch boolValue]? UIKeyboardTypeDefault: UIKeyboardTypeURL;
if (!key || [key isEqualToString:NSStringFromSelector( @selector( hidePasswords ) )])
[self.passwordCollectionView reloadData];
[self.collectionView reloadData];
}
- (void)reloadPasswords {
- (void)reloadSites {
[self.fetchedResultsController.managedObjectContext performBlock:^{
static NSRegularExpression *fuzzyRE;
@@ -395,7 +386,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
[fuzzyGroups addObject:[queryString substringWithRange:result.range]];
}];
_fuzzyGroups = fuzzyGroups;
self.fuzzyGroups = fuzzyGroups;
NSError *error = nil;
self.fetchedResultsController.fetchRequest.predicate =
@@ -404,11 +395,11 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
MPError( error, @"Couldn't fetch sites." );
PearlMainQueue( ^{
[self.passwordCollectionView updateDataSource:_passwordCollectionSections
toSections:[self createPasswordCollectionSections]
reloadItems:@[ MPTransientPasswordItem ] completion:^(BOOL finished) {
for (MPPasswordCell *cell in self.passwordCollectionView.visibleCells)
[cell setFuzzyGroups:_fuzzyGroups];
[self.collectionView updateDataSource:self.dataSource
toSections:[self createPasswordCollectionSections]
reloadItems:@[ MPTransientPasswordItem ] completion:^(BOOL finished) {
for (MPSiteCell *cell in self.collectionView.visibleCells)
[cell setFuzzyGroups:self.fuzzyGroups];
}];
} );
}];
@@ -418,33 +409,33 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (NSString *)query {
return [self.passwordsSearchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
return [self.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
- (void)setQuery:(NSString *)query {
self.passwordsSearchBar.text = [query stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[self reloadPasswords];
self.searchBar.text = [query stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[self reloadSites];
}
- (NSFetchedResultsController *)fetchedResultsController {
if (!_fetchedResultsController) {
if (!self.fetchedResultsController) {
[MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
fetchRequest.sortDescriptors = @[
[[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO]
];
fetchRequest.fetchBatchSize = 10;
_fetchedResultsController =
self.fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:mainContext
sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
self.fetchedResultsController.delegate = self;
}];
[self registerObservers];
}
return _fetchedResultsController;
return self.fetchedResultsController;
}
- (void)setActive:(BOOL)active {
@@ -458,7 +449,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
[UIView animateWithDuration:animated? 0.4f: 0 animations:^{
[self.navigationBarToTopConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh];
[self.passwordsToBottomConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh];
[self.sitesToBottomConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh];
[self.view layoutIfNeeded];
} completion:completion];
}
@@ -467,8 +458,8 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (IBAction)dismissPopdown:(id)sender {
if (_popdownVC)
[[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:_popdownVC destination:self] perform];
if (self.popdownVC)
[[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:self.popdownVC destination:self] perform];
else
self.popdownToTopConstraint.priority = UILayoutPriorityDefaultHigh;
}

View File

@@ -20,7 +20,7 @@
#import "MPiOSAppDelegate.h"
#import "UIColor+Expanded.h"
#import "MPAppDelegate_InApp.h"
#import "MPPasswordsViewController.h"
#import "MPSitesViewController.h"
PearlEnum( MPDevelopmentFuelConsumption,
MPDevelopmentFuelConsumptionQuarterly, MPDevelopmentFuelConsumptionMonthly, MPDevelopmentFuelWeekly );
@@ -191,11 +191,11 @@ PearlEnum( MPDevelopmentFuelConsumption,
#pragma mark - Private
- (MPPasswordsViewController *)dismissPopup {
- (MPSitesViewController *)dismissPopup {
for (UIViewController *vc = self; (vc = vc.parentViewController);)
if ([vc isKindOfClass:[MPPasswordsViewController class]]) {
MPPasswordsViewController *passwordsVC = (MPPasswordsViewController *)vc;
if ([vc isKindOfClass:[MPSitesViewController class]]) {
MPSitesViewController *passwordsVC = (MPSitesViewController *)vc;
[passwordsVC dismissPopdown:self];
return passwordsVC;
}

View File

@@ -54,19 +54,19 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
@property(nonatomic, strong) NSTimer *marqueeTipTimer;
@property(nonatomic, strong) NSArray *marqueeTipTexts;
@property(nonatomic) NSUInteger marqueeTipTextIndex;
@property(nonatomic, copy) NSString *masterPasswordChoice;
@property(nonatomic, strong) NSOperationQueue *afterUpdates;
@property(nonatomic, weak) id contextChangedObserver;
@end
@implementation MPUsersViewController {
NSString *_masterPasswordChoice;
NSOperationQueue *_afterUpdates;
__weak id _contextChangedObserver;
}
@implementation MPUsersViewController
- (void)viewDidLoad {
[super viewDidLoad];
_afterUpdates = [NSOperationQueue new];
self.afterUpdates = [NSOperationQueue new];
self.marqueeTipTexts = @[
strl( @"Thanks, lhunath ➚" ),
@@ -205,7 +205,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
return NO;
}
if (![masterPassword isEqualToString:_masterPasswordChoice]) {
if (![masterPassword isEqualToString:self.masterPasswordChoice]) {
// Master password confirmation failed.
[self showEntryTip:strl( @"Looks like a typo!\nTry again; enter your master password twice." )];
self.activeUserState = MPActiveUserStateMasterPasswordChoice;
@@ -655,7 +655,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
- (void)afterUpdatesMainQueue:(void ( ^ )(void))block {
[_afterUpdates addOperationWithBlock:^{
[self.afterUpdates addOperationWithBlock:^{
PearlMainQueue( block );
}];
}
@@ -664,15 +664,15 @@ referenceSizeForFooterInSection:(NSInteger)section {
[self removeKeyPathObservers];
PearlRemoveNotificationObservers();
[[NSNotificationCenter defaultCenter] removeObserver:_contextChangedObserver];
[[NSNotificationCenter defaultCenter] removeObserver:self.contextChangedObserver];
}
- (void)registerObservers {
[self removeObservers];
[self observeKeyPath:@"avatarCollectionView.contentOffset" withBlock:
^(id from, id to, NSKeyValueChange cause, MPUsersViewController *_self) {
[_self updateAvatarVisibility];
^(id from, id to, NSKeyValueChange cause, MPUsersViewController *self) {
[self updateAvatarVisibility];
}];
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
@@ -696,13 +696,14 @@ referenceSizeForFooterInSection:(NSInteger)section {
[self.keyboardHeightConstraint updateConstant:keyboardHeight];
} );
if ((_contextChangedObserver = [MPiOSAppDelegate managedObjectContextChanged:^(NSDictionary<NSManagedObjectID *, NSString *> *affectedObjects) {
if ([[[affectedObjects allKeys] filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(NSManagedObjectID *objectID, NSDictionary *bindings) {
return [objectID.entity.name isEqualToString:NSStringFromClass( [MPUserEntity class] )];
}]] count])
[self reloadUsers];
}]))
if ((self.contextChangedObserver
= [MPiOSAppDelegate managedObjectContextChanged:^(NSDictionary<NSManagedObjectID *, NSString *> *affectedObjects) {
if ([[[affectedObjects allKeys] filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(NSManagedObjectID *objectID, NSDictionary *bindings) {
return [objectID.entity.name isEqualToString:NSStringFromClass( [MPUserEntity class] )];
}]] count])
[self reloadUsers];
}]))
[UIView animateWithDuration:0.3f animations:^{
self.avatarCollectionView.visible = YES;
[self.storeLoadingActivity stopAnimating];
@@ -772,7 +773,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
isNew:&isNew].permanentObjectID;
[self.avatarCollectionView reloadData];
NSUInteger selectedAvatarItem = isNew? [_userIDs count]: selectUserID? [_userIDs indexOfObject:selectUserID]: NSNotFound;
NSUInteger selectedAvatarItem = isNew? [self.userIDs count]: selectUserID? [self.userIDs indexOfObject:selectUserID]: NSNotFound;
if (selectedAvatarItem != NSNotFound)
[self.avatarCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:selectedAvatarItem inSection:0] animated:NO
scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
@@ -791,7 +792,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
- (void)setActiveUserState:(MPActiveUserState)activeUserState animated:(BOOL)animated {
_activeUserState = activeUserState;
_masterPasswordChoice = nil;
self.masterPasswordChoice = nil;
if (activeUserState != MPActiveUserStateMinimized && (!self.active || [MPiOSAppDelegate get].activeUserOID)) {
[[MPiOSAppDelegate get] signOutAnimated:YES];
@@ -799,7 +800,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
}
// Set the entry container's contents.
[_afterUpdates setSuspended:YES];
[self.afterUpdates setSuspended:YES];
__block BOOL requestFirstResponder = NO;
[self.view layoutIfNeeded];
[UIView animateWithDuration:animated? 0.4f: 0 animations:^{
@@ -828,7 +829,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
break;
}
case MPActiveUserStateMasterPasswordConfirmation: {
_masterPasswordChoice = self.entryField.text;
self.masterPasswordChoice = self.entryField.text;
self.entryLabel.text = strl( @"Confirm your master password:" );
self.entryField.secureTextEntry = YES;
self.entryField.autocapitalizationType = UITextAutocapitalizationTypeNone;
@@ -890,7 +891,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[_afterUpdates setSuspended:NO];
[self.afterUpdates setSuspended:NO];
}];
[self.entryField resignFirstResponder];

View File

@@ -1,137 +1,137 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>M. Password</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>mpsites</string>
</array>
<key>CFBundleTypeIconFiles</key>
<array>
<string>Icon-Small</string>
</array>
<key>CFBundleTypeName</key>
<string>Master Password sites</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.lyndir.masterpassword.sites</string>
</array>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>[auto]</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>[auto]</string>
<key>Fabric</key>
<dict>
<key>APIKey</key>
<string>0d10c90776f5ef5acd01ddbeaca9a6cba4814560</string>
<key>Kits</key>
<array>
<dict>
<key>KitInfo</key>
<dict/>
<key>KitName</key>
<string>Crashlytics</string>
</dict>
</array>
</dict>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>© 2011-2017</string>
<key>UIAppFonts</key>
<array>
<string>Exo2.0-Bold.otf</string>
<string>Exo2.0-ExtraBold.otf</string>
<string>Exo2.0-Regular.otf</string>
<string>Exo2.0-Thin.otf</string>
<string>SourceCodePro-Black.otf</string>
<string>SourceCodePro-Regular.otf</string>
<string>SourceCodePro-ExtraLight.otf</string>
</array>
<key>UIMainStoryboardFile</key>
<string>Storyboard</string>
<key>UIStatusBarHidden</key>
<true/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>TintColor</key>
<dict>
<key>Blue</key>
<real>0.42745098039215684</real>
<key>Green</key>
<real>0.39215686274509803</real>
<key>Red</key>
<real>0.37254901960784315</real>
</dict>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.utf8-plain-text</string>
</array>
<key>UTTypeDescription</key>
<string>Master Password sites</string>
<key>UTTypeIdentifier</key>
<string>com.lyndir.masterpassword.sites</string>
<key>UTTypeSize320IconFile</key>
<string>Icon-320.png</string>
<key>UTTypeSize64IconFile</key>
<string>Icon-64.png</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>mpsites</string>
</array>
</dict>
</dict>
</array>
</dict>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>M. Password</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>mpsites</string>
</array>
<key>CFBundleTypeIconFiles</key>
<array>
<string>Icon-Small</string>
</array>
<key>CFBundleTypeName</key>
<string>Master Password sites</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.lyndir.masterpassword.sites</string>
</array>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>[auto]</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>[auto]</string>
<key>Fabric</key>
<dict>
<key>APIKey</key>
<string>0d10c90776f5ef5acd01ddbeaca9a6cba4814560</string>
<key>Kits</key>
<array>
<dict>
<key>KitInfo</key>
<dict/>
<key>KitName</key>
<string>Crashlytics</string>
</dict>
</array>
</dict>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>© 2011-2017</string>
<key>UIAppFonts</key>
<array>
<string>Exo2.0-Bold.otf</string>
<string>Exo2.0-ExtraBold.otf</string>
<string>Exo2.0-Regular.otf</string>
<string>Exo2.0-Thin.otf</string>
<string>SourceCodePro-Black.otf</string>
<string>SourceCodePro-Regular.otf</string>
<string>SourceCodePro-ExtraLight.otf</string>
</array>
<key>UIMainStoryboardFile</key>
<string>Storyboard</string>
<key>UIStatusBarHidden</key>
<true/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>TintColor</key>
<dict>
<key>Blue</key>
<real>0.42745098039215684</real>
<key>Green</key>
<real>0.39215686274509803</real>
<key>Red</key>
<real>0.37254901960784315</real>
</dict>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.utf8-plain-text</string>
</array>
<key>UTTypeDescription</key>
<string>Master Password sites</string>
<key>UTTypeIdentifier</key>
<string>com.lyndir.masterpassword.sites</string>
<key>UTTypeSize320IconFile</key>
<string>Icon-320.png</string>
<key>UTTypeSize64IconFile</key>
<string>Icon-64.png</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>mpsites</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>

View File

@@ -1,20 +1,20 @@
/**
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
*
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// NSString(MPMarkDown).h
// NSString(MPMarkDown)
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Created by lhunath on 2014-09-28.
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Foundation/Foundation.h>

View File

@@ -1,20 +1,20 @@
/**
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
*
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// NSString(MPMarkDown).h
// NSString(MPMarkDown)
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Created by lhunath on 2014-09-28.
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "NSString+MPMarkDown.h"
#import "markdown_lib.h"

File diff suppressed because it is too large Load Diff