2
0

Compare commits

...

19 Commits

Author SHA1 Message Date
Maarten Billemont
5db294bdb3 Show purchase transaction failures to the user. 2020-05-23 19:58:47 -04:00
Maarten Billemont
fee7bc7401 Resolve site cell sizing issues across window sizes. 2020-05-23 19:08:43 -04:00
Maarten Billemont
21968f4ba6 Fix messages for password reset. 2020-05-23 12:35:55 -04:00
Maarten Billemont
8582c934c2 Limit fuzzy searching to a depth of 10.
Avoids choking when query string becomes long and there are excessively
long site name entries.
2020-05-23 12:14:22 -04:00
Maarten Billemont
7091e2ee1b Disable automatic font scaling.
It's causing issues with pop-up alerts.
2020-05-23 10:12:07 -04:00
Maarten Billemont
d5d455ee57 Fix issues with content insets for sites across OS versions. 2020-05-22 23:04:36 -04:00
Maarten Billemont
e6ae06798b Handle store opening errors more gracefully.
Store opening can fail for example when hard-locking the device while
it's opening up.
2020-05-22 22:26:43 -04:00
Maarten Billemont
1cae4c754b Group MPErrors together, ignoring the actual inline values. 2020-05-22 22:26:18 -04:00
Maarten Billemont
93ad86e63c Remove PearlAppDelegate. 2020-05-22 17:34:04 -04:00
Maarten Billemont
cf74dc5cc2 Updated NSMenu API. 2020-05-19 13:28:23 -04:00
Maarten Billemont
981bdb3ab4 Fix isDescendantOfView bug & Sentry script error on failure. 2020-05-19 09:21:06 -04:00
Maarten Billemont
9bea8bcbdf Sheets need a source view on iPad. 2020-05-19 08:21:44 -04:00
Maarten Billemont
363d6f6639 Test configuration was removed for Release. 2020-05-18 13:01:16 -04:00
Maarten Billemont
eb1632cb62 Install cocoapods dependencies & gradle works on JDK 11 now. 2020-05-18 12:43:37 -04:00
Maarten Billemont
73fadaef7f iOS uses Xcode 11 now. 2020-05-18 12:15:36 -04:00
Maarten Billemont
60200f6302 Fix all versions advertising themselves as V0. 2020-05-18 12:14:44 -04:00
Maarten Billemont
cce8db5c48 Purge unused and deprecated UISearchDisplayController. 2020-05-18 11:10:23 -04:00
Maarten Billemont
6f3da5ccf0 Harmonize consent features. 2020-05-16 22:34:49 -04:00
Maarten Billemont
52c87eaeca Keep sites sorted by name on export to ensure consistency. 2020-05-16 16:03:42 -04:00
26 changed files with 214 additions and 207 deletions

View File

@@ -9,10 +9,12 @@ build_project:
- "( ./lib/bin/build_libsodium-macos clean && ./lib/bin/build_libsodium-macos )"
- "( ./lib/bin/build_libjson-c-macos clean && ./lib/bin/build_libjson-c-macos )"
- "( cd ./platform-independent/c/cli && ./clean && targets=all ./build && ./mpw-tests && ./mpw-cli-tests )"
- "( export JAVA_HOME=$(java_home -Fv 10 || java_home -Fv 9* ) && ./gradlew --stacktrace clean test )"
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword iOS' -sdk iphonesimulator clean build )"
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword macOS' clean build )"
- "( ./gradlew --stacktrace --info clean test )"
- "( cd platform-darwin && pod install )"
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Release' -scheme 'MasterPassword iOS' -sdk iphonesimulator clean build )"
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Release' -scheme 'MasterPassword macOS' clean build )"
tags:
- brew
- java_9
- xcode_9
- java
- cocoapods
- xcode

View File

@@ -174,7 +174,6 @@
DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA67460C18DE7F0C00DFE240 /* Exo2.0-Bold.otf */; };
DA69540617D975D900BF294E /* icon_gears.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37841711E29500CF925C /* icon_gears.png */; };
DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37851711E29500CF925C /* icon_gears@2x.png */; };
DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */ = {isa = PBXBuildFile; fileRef = DACE2F6719BA6A2A0010F92E /* UIView+FontScale.m */; };
DA72E2302453B91700676D4F /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA72E22F2453B91700676D4F /* WebKit.framework */; };
DA73049D194E022700E72520 /* ui_spinner.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36511711E29400CF925C /* ui_spinner.png */; };
DA73049E194E022700E72520 /* ui_spinner@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36521711E29400CF925C /* ui_spinner@2x.png */; };
@@ -3161,7 +3160,7 @@
DA5BFA42147E415C00F98B1E /* Resources */,
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */,
4A87858EE3659604089E2F9F /* [CP] Embed Pods Frameworks */,
DA3C4EB32439438B00A6C4A8 /* Upload Sentry dSYM */,
DA3C4EB32439438B00A6C4A8 /* Sentry dSYM Upload */,
);
buildRules = (
);
@@ -3518,7 +3517,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
DA3C4EB32439438B00A6C4A8 /* Upload Sentry dSYM */ = {
DA3C4EB32439438B00A6C4A8 /* Sentry dSYM Upload */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
@@ -3526,15 +3525,16 @@
inputFileListPaths = (
);
inputPaths = (
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}",
);
name = "Upload Sentry dSYM";
name = "Sentry dSYM Upload";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/sh -e";
shellScript = "if hash sentry-cli 2>/dev/null; then\n if ! ERROR=$(SENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-ios sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null); then\n echo >&2 \"warning: sentry-cli: $ERROR\"\n fi\nelse\n echo >&2 \"warning: sentry-cli not installed: try brew install getsentry/tools/sentry-cli\"\nfi\n";
shellScript = "if ! hash sentry-cli 2>/dev/null; then\n echo >&2 \"error: sentry-cli not installed. Try brew install getsentry/tools/sentry-cli\"\n exit 1\nfi\n\nSENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-ios sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\"\n";
showEnvVarsInLog = 0;
};
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */ = {
@@ -3682,7 +3682,6 @@
DAFE4A2E15039824003ABA7C /* PearlStrings.m in Sources */,
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */,
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */,
DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */,
DAFE4A4115039824003ABA7C /* PearlArrayTVC.m in Sources */,
DAFE4A4315039824003ABA7C /* PearlBoxView.m in Sources */,

View File

@@ -2329,7 +2329,7 @@
DAD9B5EE1762CA3A001835F9 /* Copy LoginHelper */,
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */,
43E5966C8C236E86824DDADE /* [CP] Embed Pods Frameworks */,
DA3C4EB2243941AE00A6C4A8 /* Upload Sentry dSYM */,
DA3C4EB2243941AE00A6C4A8 /* Sentry dSYM Upload */,
);
buildRules = (
);
@@ -2585,7 +2585,7 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MasterPassword-macOS/Pods-MasterPassword-macOS-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
DA3C4EB2243941AE00A6C4A8 /* Upload Sentry dSYM */ = {
DA3C4EB2243941AE00A6C4A8 /* Sentry dSYM Upload */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
@@ -2593,15 +2593,16 @@
inputFileListPaths = (
);
inputPaths = (
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}",
);
name = "Upload Sentry dSYM";
name = "Sentry dSYM Upload";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/sh -e";
shellScript = "if hash sentry-cli 2>/dev/null; then\n if ! ERROR=$(SENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-macos sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\" 2>&1 >/dev/null); then\n echo >&2 \"warning: sentry-cli: $ERROR\"\n fi\nelse\n echo >&2 \"warning: sentry-cli not installed: try brew install getsentry/tools/sentry-cli\"\nfi\n";
shellScript = "if ! hash sentry-cli 2>/dev/null; then\n echo >&2 \"error: sentry-cli not installed. Try brew install getsentry/tools/sentry-cli\"\n exit 1\nfi\n\nSENTRY_ORG=lyndir SENTRY_PROJECT=masterpassword-macos sentry-cli upload-dif --log-level info \"$DWARF_DSYM_FOLDER_PATH\"\n";
showEnvVarsInLog = 0;
};
DA4EF9CB19FD4B600032ECB5 /* Run Script: genassets */ = {

View File

@@ -117,7 +117,7 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
[self performPurchaseProductWithIdentifier:productIdentifier quantity:quantity];
}]];
[controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:controller animated:YES completion:nil];
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
return;
}
#endif
@@ -158,16 +158,16 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
MPError( error, @"StoreKit request (%@) failed.", request );
MPError( error, @"StoreKit request failed." );
#if TARGET_OS_IPHONE
PearlMainQueue( ^{
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Purchase Failed" message:
strf( @"%@\n\n%@", error.localizedDescription,
@"Ensure you are online and try logging out and back into iTunes from your device's Settings." )
@"Could not reach Apple's iTunes Store. Make sure you're connected to the Internet and try again." )
preferredStyle:UIAlertControllerStyleAlert];
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:controller animated:YES completion:nil];
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
} );
#endif
}
@@ -222,6 +222,17 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
MPError( transaction.error, @"Transaction failed: %@.", transaction.payment.productIdentifier );
[queue finishTransaction:transaction];
#if TARGET_OS_IPHONE
PearlMainQueue( ^{
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Purchase Failed" message:
strf( @"%@\n\n%@", transaction.error.localizedDescription,
@"Could not reach Apple's iTunes Store. Make sure you're connected to the Internet and try again." )
preferredStyle:UIAlertControllerStyleAlert];
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
} );
#endif
SKProduct *product = self.products[transaction.payment.productIdentifier];
[Countly.sharedInstance recordEvent:@"purchase" segmentation:@{
@"id": product.productIdentifier,

View File

@@ -249,18 +249,18 @@
masterPassword = PearlAwait( ^(void (^setResult)(id)) {
PearlMainQueue( ^{
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Enter Old Master Password" message:
strf( @"Your old master password is required to migrate the stored password for %@", site.name )
strf( @"Your old master password is required to unlock the stored password for: <%@>", site.name )
preferredStyle:UIAlertControllerStyleAlert];
[controller addTextFieldWithConfigurationHandler:nil];
[controller addAction:[UIAlertAction actionWithTitle:@"Migrate" style:UIAlertActionStyleDefault handler:
^(UIAlertAction *_Nonnull action) {
setResult( controller.textFields.firstObject.text );
}]];
[controller addAction:[UIAlertAction actionWithTitle:@"Don't Migrate" style:UIAlertActionStyleCancel handler:
[controller addAction:[UIAlertAction actionWithTitle:@"Leave It" style:UIAlertActionStyleCancel handler:
^(UIAlertAction *_Nonnull action) {
setResult( nil );
}]];
[self.navigationController presentViewController:controller animated:YES completion:nil];
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
} );
} );
#endif

View File

@@ -20,7 +20,7 @@
#if TARGET_OS_IPHONE
@interface MPAppDelegate_Shared : PearlAppDelegate
@interface MPAppDelegate_Shared : UIResponder<UIApplicationDelegate, PearlConfigDelegate>
#else

View File

@@ -30,6 +30,7 @@
- (id)managedObjectContextChanged:(void ( ^ )(NSDictionary<NSManagedObjectID *, NSString *> *affectedObjects))changedBlock;
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context;
- (void)retryCorruptStore;
- (void)deleteAndResetStore;
/** @param completion The block to execute after adding the site, executed from the main thread with the new site in the main MOC. */

View File

@@ -232,22 +232,27 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
}];
} );
// Create a new store coordinator.
NSError *error = nil;
NSURL *localStoreURL = [self localStoreURL];
if (![[NSFileManager defaultManager] createDirectoryAtURL:[localStoreURL URLByDeletingLastPathComponent]
withIntermediateDirectories:YES attributes:nil error:&error]) {
MPError( error, @"Couldn't create our application support directory." );
PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext );
self.mainManagedObjectContext = nil;
self.privateManagedObjectContext = nil;
return;
}
if (![self.storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self localStoreURL]
if (![self.storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:localStoreURL
options:@{
NSMigratePersistentStoresAutomaticallyOption: @YES,
NSInferMappingModelAutomaticallyOption : @YES,
STORE_OPTIONS
} error:&error]) {
MPError( error, @"Failed to open store." );
PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext );
self.mainManagedObjectContext = nil;
self.privateManagedObjectContext = nil;
self.storeCorrupted = @YES;
[self handleCoordinatorError:error];
return;
@@ -274,6 +279,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
}];
}
- (void)retryCorruptStore {
self.storeCorrupted = @NO;
[self loadStore];
}
- (void)deleteAndResetStore {
@synchronized (self) {
@@ -728,7 +739,9 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
exportUser->defaultType = user.defaultType;
exportUser->lastUsed = (time_t)user.lastUsed.timeIntervalSince1970;
for (MPSiteEntity *site in user.sites) {
for (MPSiteEntity *site in [user.sites sortedArrayUsingDescriptors:@[
[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]
]]) {
MPCounterValue counter = MPCounterValueInitial;
if ([site isKindOfClass:[MPGeneratedSiteEntity class]])
counter = ((MPGeneratedSiteEntity *)site).counter;

View File

@@ -43,6 +43,7 @@ __END_DECLS
SentryEvent *event = [[SentryEvent alloc] initWithLevel:kSentryLevelError]; \
event.message = strf( message_ @": %@", ##__VA_ARGS__, [__error localizedDescription]); \
event.logger = @"MPError"; \
event.fingerprint = @[ message_, __error.domain, @(__error.code) ]; \
[SentrySDK captureEvent:event]; \
} \
__error; \

View File

@@ -12,9 +12,6 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<point key="canvasLocation" x="139" y="155"/>
</menu>
<customObject id="494" customClass="MPMacAppDelegate">
<connections>
<outlet property="createUserItem" destination="757" id="763"/>
@@ -241,6 +238,9 @@
</connections>
</menuItem>
</items>
<connections>
<outlet property="delegate" destination="494" id="Slu-zT-yO4"/>
</connections>
<point key="canvasLocation" x="140" y="23"/>
</menu>
</objects>

View File

@@ -21,9 +21,9 @@
#import "MPSitesWindowController.h"
#import "MPInitialWindowController.h"
@interface MPMacAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate>
@interface MPMacAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate, NSMenuDelegate>
@property(nonatomic, strong) NSStatusItem *statusView;
@property(nonatomic, strong) NSStatusItem *statusItem;
@property(nonatomic, strong) MPSitesWindowController *sitesWindowController;
@property(nonatomic, strong) MPInitialWindowController *initialWindowController;
@property(nonatomic, weak) IBOutlet NSMenuItem *lockItem;

View File

@@ -158,12 +158,10 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
} forKeyPath:@"activeUser" options:0 context:nil];
// Status item.
self.statusView = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
self.statusView.image = [NSImage imageNamed:@"menu-icon"];
self.statusView.image.template = YES;
self.statusView.menu = self.statusMenu;
self.statusView.target = self;
self.statusView.action = @selector( showMenu );
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
self.statusItem.menu = self.statusMenu;
self.statusItem.button.image = [NSImage imageNamed:@"menu-icon"];
self.statusItem.button.image.template = YES;
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, self.storeCoordinator, nil,
^(id self, NSNotification *note) {
@@ -502,7 +500,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
- (IBAction)showPopup:(id)sender {
[self.statusView popUpStatusItemMenu:self.statusView.menu];
[[self.statusItem button] performClick:sender];
}
- (IBAction)showPasswordWindow:(id)sender {
@@ -682,13 +680,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
[self updateMenuItems];
}
- (void)showMenu {
[self updateMenuItems];
[self.statusView popUpStatusItemMenu:self.statusView.menu];
}
- (void)updateMenuItems {
MPUserEntity *activeUser = [self activeUserForMainThread];
@@ -743,6 +734,13 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
}
}
#pragma mark - NSMenuDelegate
- (void)menuNeedsUpdate:(NSMenu *)menu {
[self updateMenuItems];
}
#pragma mark - PearlConfigDelegate
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
@@ -763,13 +761,9 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
// Send info
NSArray *countlyFeatures = @[
CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
CLYConsentSessions, CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
];
if ([[MPConfig get].sendInfo boolValue] || ![[MPConfig get].sendInfoDecided boolValue])
[Countly.sharedInstance giveConsentForFeature:CLYConsentSessions];
else
[Countly.sharedInstance cancelConsentForFeature:CLYConsentSessions];
if ([[MPMacConfig get].sendInfo boolValue]) {
if ([[MPMacConfig get].sendInfo boolValue] || ![[MPMacConfig get].sendInfoDecided boolValue]) {
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
[PearlLogger get].printLevel = PearlLogLevelInfo;

View File

@@ -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;

View File

@@ -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] )];

View File

@@ -53,13 +53,10 @@
if (![[MPMacConfig get].sendInfoDecided boolValue]) {
NSAlert *alert = [NSAlert new];
alert.messageText = @"Welcome to Master Password!";
alert.informativeText = @"We want you to have a top-notch experience.\n"
@"Using diagnostics, we ensure the application keeps working as designed for you.\n"
@"\n"
@"We look out for application bugs, runtime issues, sudden crashes & usage counters.\n"
@"Needless to say, diagnostics are always scrubbed and personal details will never leave your device.";
[alert addButtonWithTitle:@"Thanks!"];
alert.messageText = @"Diagnostics";
alert.informativeText = @"We look for bugs, sudden crashes, runtime issues & statistics.\n\n"
@"Diagnostics are scrubbed and personal details will never leave your device.";
[alert addButtonWithTitle:@"Engage"];
[alert addButtonWithTitle:@"Disable"];
[alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
[MPMacConfig get].sendInfo = @(returnCode != NSAlertSecondButtonReturn);
@@ -614,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" );
@@ -651,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 );

View File

@@ -27,7 +27,7 @@ typedef NS_ENUM ( NSUInteger, MPSiteCellMode ) {
@interface MPSiteCell : MPCell<UIScrollViewDelegate, UITextFieldDelegate>
@property(nonatomic) NSArray *fuzzyGroups;
@property(nonatomic) NSArray *queryGroups;
- (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated;
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;

View File

@@ -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)

View File

@@ -36,7 +36,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
@interface MPSitesViewController()<NSFetchedResultsControllerDelegate>
@property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@property(nonatomic, strong) NSArray *fuzzyGroups;
@property(nonatomic, strong) NSArray *queryGroups;
@property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet;
@property(nonatomic, strong) NSMutableArray<NSMutableArray *> *dataSource;
@property(nonatomic, weak) UIViewController *popdownVC;
@@ -120,12 +120,14 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
PearlRemoveNotificationObservers();
}
- (void)viewWillLayoutSubviews {
- (void)viewDidLayoutSubviews {
self.collectionView.contentInset = [self.collectionView occludedInsets];
self.collectionView.scrollIndicatorInsets = self.collectionView.contentInset;
[super viewDidLayoutSubviews];
[super viewWillLayoutSubviews];
if (@available( iOS 11, * )) {
self.collectionView.layoutMargins =
UIEdgeInsetsMake( [self.collectionView occludedInsets].top - self.view.safeAreaInsets.top, 0, 0, 0 );
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
@@ -160,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];
@@ -170,6 +172,19 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
return cell;
}
#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout;
CGFloat availableWidth = collectionView.bounds.size.width
- collectionView.layoutMargins.left - collectionView.layoutMargins.right
- layout.sectionInset.left - layout.sectionInset.right;
CGFloat cells = MAX( 1, (int)((availableWidth + layout.minimumInteritemSpacing) / (318 + layout.minimumInteritemSpacing)) );
return CGSizeMake( (availableWidth - layout.minimumInteritemSpacing * (cells - 1)) / cells, 100 );
}
#pragma mark - UIScrollDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
@@ -353,21 +368,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 =
@@ -380,7 +393,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];
}];
} );
}];

View File

@@ -100,9 +100,10 @@ decisionHandler:(void ( ^ )(WKNavigationActionPolicy))decisionHandler {
- (IBAction)action:(id)sender {
UIAlertController *controller = [UIAlertController new];
controller.title = self.webView.URL.host;
controller.message = self.webView.URL.absoluteString;
UIAlertController *controller = [UIAlertController alertControllerWithTitle:self.webView.URL.host
message:self.webView.URL.absoluteString
preferredStyle:UIAlertControllerStyleActionSheet];
[controller.popoverPresentationController setSourceView:sender];
[controller addAction:[UIAlertAction actionWithTitle:@"Safari" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[UIApp openURL:self.webView.URL];
}]];

View File

@@ -23,6 +23,7 @@
@interface MPiOSAppDelegate : MPAppDelegate_Shared <SKStoreProductViewControllerDelegate>
@property(nonatomic, strong) UIWindow *window;
@property(nonatomic, strong) SKStoreProductViewController *voltoViewController;
- (void)openURL:(NSURL *)url;

View File

@@ -35,7 +35,7 @@
@implementation CountlyPushNotifications(MPNotifications)
- (void)openURL:(NSString *)URLString {
[[MPiOSAppDelegate get].navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:URLString]];
[[MPiOSAppDelegate get].window.rootViewController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:URLString]];
}
@end
@@ -48,6 +48,8 @@
@implementation MPiOSAppDelegate
@synthesize window;
+ (void)initialize {
[MPiOSConfig get];
@@ -150,12 +152,6 @@
@catch (id exception) {
err( @"During Config Test: %@", exception );
}
@try {
[super application:application didFinishLaunchingWithOptions:launchOptions];
}
@catch (id exception) {
err( @"During Pearl Application Launch: %@", exception );
}
@try {
inf( @"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier] );
@@ -190,8 +186,8 @@
[migrateVC loadProductWithParameters:@{
SKStoreProductParameterCampaignToken : @"app-masterpassword.ios", /* Campaign: From MasterPassword iOS */
SKStoreProductParameterProviderToken : @153897, /* Provider: Maarten Billemont */
SKStoreProductParameterITunesItemIdentifier: @510296984, /* Application: MasterPassword iOS */
//SKStoreProductParameterITunesItemIdentifier: @1500430196, /* Application: Volto iOS */
// SKStoreProductParameterITunesItemIdentifier: @510296984, /* Application: MasterPassword iOS */
SKStoreProductParameterITunesItemIdentifier: @1500430196, /* Application: Volto iOS */
} completionBlock:^(BOOL result, NSError *error) {
if (error)
err( @"Failed loading Volto product information: %@", error );
@@ -205,9 +201,8 @@
}];
PearlMainQueueOperation( ^{
[self.navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:@"masterpassword://foo?bar=quux"]];
if ([[MPiOSConfig get].showSetup boolValue])
[self.navigationController performSegueWithIdentifier:@"setup" sender:self];
[self.window.rootViewController performSegueWithIdentifier:@"setup" sender:self];
[self consentFeatures];
} );
@@ -245,7 +240,7 @@
(id)[error localizedDescription]?: error )
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
return;
}
@@ -257,7 +252,7 @@
@"Master Password couldn't understand the import file."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
return;
}
@@ -297,8 +292,7 @@
[self consentFeatures];
}]];
[(self.navigationController.presentedViewController?: (UIViewController *)self.navigationController)
presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
return YES;
@@ -343,8 +337,7 @@
[MPiOSConfig get].notificationsDecided = @(YES);
}
}]];
[(self.navigationController.presentedViewController?: (UIViewController *)self.navigationController)
presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
}
@@ -373,7 +366,7 @@
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
setResult( nil );
}]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
} );
} askUserPassword:^NSString *(NSString *userName) {
@@ -391,7 +384,7 @@
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
setResult( nil );
}]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
} );
} result:^(NSError *error) {
@@ -402,7 +395,7 @@
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Error" message:[error localizedDescription]
preferredStyle:UIAlertControllerStyleAlert];
[controller addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:controller animated:YES completion:nil];
[self.window.rootViewController presentViewController:controller animated:YES completion:nil];
}
} );
}];
@@ -412,8 +405,6 @@
inf( @"Will foreground" );
[super applicationWillEnterForeground:application];
[self.hangDetector start];
}
@@ -436,20 +427,16 @@
[UIPasteboard generalPasteboard].string = @"";
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
}
mpw_marshal_file_free( &importFile );
} );
[super applicationDidBecomeActive:application];
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
inf( @"Received memory warning." );
[super applicationDidReceiveMemoryWarning:application];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
@@ -462,8 +449,6 @@
}
[self.hangDetector stop];
[super applicationDidEnterBackground:application];
}
#pragma mark - Behavior
@@ -480,7 +465,7 @@
else if ([url.host isEqualToString:@"show-url"]) {
for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems)
if ([item.name isEqualToString:@"url"]) {
[[MPiOSAppDelegate get].navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:item.value]];
[self.window.rootViewController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:item.value]];
return;
}
}
@@ -513,7 +498,7 @@
@"help@masterpassword.app"
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
else if (logs) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Feedback" message:
@@ -527,7 +512,7 @@
[alert addAction:[UIAlertAction actionWithTitle:@"No Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self openFeedbackWithLogs:NO forVC:viewController];
}]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
else
[self openFeedbackWithLogs:NO forVC:viewController];
@@ -573,15 +558,16 @@
@"This may be due to corruption. You can either reset Master Password and "
@"recreate your user, or E-Mail us your logs and leave your corrupt store as-is for now."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"E-Mail Logs" style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self openFeedbackWithLogs:YES forVC:nil];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Try Again" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self retryCorruptStore];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Send Logs" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self openFeedbackWithLogs:YES forVC:nil];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Reset" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self deleteAndResetStore];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Ignore" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
} );
}
@@ -606,10 +592,10 @@
[self showExportRevealPasswords:YES forVC:viewController];
}]];
[sheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:sheet animated:YES completion:nil];
[self.window.rootViewController presentViewController:sheet animated:YES completion:nil];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
- (void)showExportRevealPasswords:(BOOL)revealPasswords forVC:(UIViewController *)viewController {
@@ -620,7 +606,7 @@
@"Close Master Password, go into Settings and add a Mail account."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
return;
}
@@ -645,7 +631,7 @@
handler:^(UIAlertAction *action) {
setResult( nil );
}]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
} );
} error:&error];
@@ -656,7 +642,7 @@
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error" message:[error localizedDescription]
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
if (!exportedUser)
return;
@@ -712,7 +698,7 @@
}
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
}];
}
@@ -736,7 +722,7 @@
^(UIAlertAction *action) { [self migrateFor:user_]; }]];
PearlMainQueue( ^{
[self.navigationController presentViewController:usersSheet animated:YES completion:nil];
[self.window.rootViewController presentViewController:usersSheet animated:YES completion:nil];
} );
}];
return;
@@ -758,7 +744,7 @@
^(UIAlertAction *action) { setResult( alert.textFields.firstObject.text ); }]];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:
^(UIAlertAction *action) { setResult( nil ); }]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
} );
} error:&error];
@@ -770,7 +756,7 @@
message:[error localizedDescription]
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
if (!exportedUser)
return;
@@ -785,7 +771,7 @@
}
else if (self.voltoViewController)
[self.navigationController presentViewController:self.voltoViewController animated:YES completion:nil];
[self.window.rootViewController presentViewController:self.voltoViewController animated:YES completion:nil];
}
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset {
@@ -796,7 +782,7 @@
@"Changing your master password will cause all your generated passwords to change!\n"
@"Changing the master password back to the old one will cause your passwords to revert as well."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Abort" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[moc performBlockAndWait:^{
inf( @"Clearing keyID for user: %@.", user.userID );
user.keyID = nil;
@@ -809,7 +795,7 @@
didReset();
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Abort" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
} );
}
@@ -841,20 +827,16 @@
// Send info
NSArray *countlyFeatures = @[
CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
CLYConsentSessions, CLYConsentEvents, CLYConsentUserDetails, CLYConsentCrashReporting, CLYConsentViewTracking, CLYConsentStarRating
];
if ([[MPConfig get].sendInfo boolValue] || ![[MPConfig get].sendInfoDecided boolValue])
[Countly.sharedInstance giveConsentForFeature:CLYConsentSessions];
else
[Countly.sharedInstance cancelConsentForFeature:CLYConsentSessions];
if ([[MPConfig get].sendInfo boolValue]) {
if ([[MPiOSConfig get].sendInfo boolValue] || ![[MPiOSConfig get].sendInfoDecided boolValue]) {
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
[PearlLogger get].printLevel = PearlLogLevelInfo;
[SentrySDK.currentHub getClient].options.enabled = @YES;
[SentrySDK configureScope:^(SentryScope *scope) {
[scope setExtraValue:[MPConfig get].rememberLogin forKey:@"rememberLogin"];
[scope setExtraValue:[MPConfig get].sendInfo forKey:@"sendInfo"];
[scope setExtraValue:[MPiOSConfig get].rememberLogin forKey:@"rememberLogin"];
[scope setExtraValue:[MPiOSConfig get].sendInfo forKey:@"sendInfo"];
[scope setExtraValue:[MPiOSConfig get].helpHidden forKey:@"helpHidden"];
[scope setExtraValue:[MPiOSConfig get].showSetup forKey:@"showQuickStart"];
[scope setExtraValue:[PearlConfig get].firstRun forKey:@"firstRun"];
@@ -871,9 +853,8 @@
#else
[scope setExtraValue:@(NO) forKey:@"reviewedVersion"];
#endif
[Countly.sharedInstance giveConsentForFeatures:countlyFeatures];
}];
[Countly.sharedInstance giveConsentForFeatures:countlyFeatures];
}
else {
[Countly.sharedInstance cancelConsentForFeatures:countlyFeatures];

View File

@@ -33,8 +33,8 @@
NSStringFromSelector( @selector( siteInfoHidden ) ) : @YES,
NSStringFromSelector( @selector( showSetup ) ) : @YES,
NSStringFromSelector( @selector( appleID ) ) : @"510296984",
NSStringFromSelector( @selector( actionsTipShown ) ) : @(!self.firstRun),
NSStringFromSelector( @selector( typeTipShown ) ) : @(!self.firstRun),
NSStringFromSelector( @selector( actionsTipShown ) ) : @(![self.firstRun boolValue]),
NSStringFromSelector( @selector( typeTipShown ) ) : @(![self.firstRun boolValue]),
NSStringFromSelector( @selector( loginNameTipShown ) ): @NO,
NSStringFromSelector( @selector( traceMode ) ) : @NO,
NSStringFromSelector( @selector( dictationSearch ) ) : @NO,

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="Q1S-vU-GGO">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
@@ -97,10 +97,10 @@
</constraints>
</imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
<rect key="frame" x="43.5" y="263" width="128.5" height="16"/>
<rect key="frame" x="43.5" y="263" width="128" height="16"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
<rect key="frame" x="5" y="0.0" width="118.5" height="16"/>
<rect key="frame" x="5" y="0.0" width="118" height="16"/>
<fontDescription key="fontDescription" name="Exo2.0-ExtraBold" family="Exo 2.0" pointSize="13"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@@ -288,14 +288,14 @@
</connections>
</button>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="069-Pu-yXe" userLabel="Thanks Tip">
<rect key="frame" x="91" y="0.0" width="232.5" height="60"/>
<rect key="frame" x="90.5" y="0.0" width="233" height="60"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="Z8P-ZK-aS0">
<rect key="frame" x="0.0" y="0.0" width="232.5" height="60"/>
<rect key="frame" x="0.0" y="0.0" width="233" height="60"/>
<rect key="contentStretch" x="0.15000000000000002" y="0.0" width="0.69999999999999973" height="1"/>
</imageView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Why is Master Password free?" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="BLV-3x-Q0z">
<rect key="frame" x="20" y="11.5" width="192.5" height="17"/>
<rect key="frame" x="20" y="11.5" width="193" height="17"/>
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@@ -442,21 +442,12 @@
<outlet property="nextAvatarButton" destination="fUK-gJ-NRE" id="5qo-lK-rSa"/>
<outlet property="preferencesTipContainer" destination="0Um-Ot-hI6" id="Cv8-Bp-ZZs"/>
<outlet property="previousAvatarButton" destination="9u7-pu-Wtv" id="Hgv-lN-S1n"/>
<outlet property="searchDisplayController" destination="h98-GT-FoS" id="VvS-JO-rqq"/>
<outlet property="storeLoadingActivity" destination="VDd-oM-ZOO" id="MJ7-2f-e8n"/>
<outlet property="thanksTipContainer" destination="069-Pu-yXe" id="wWf-2X-Ryw"/>
<outlet property="userSelectionContainer" destination="rWM-08-aab" id="Yme-hX-8P0"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8hZ-Tb-wZw" userLabel="First Responder" sceneMemberID="firstResponder"/>
<searchDisplayController id="h98-GT-FoS">
<connections>
<outlet property="delegate" destination="S8q-YF-Kt9" id="hyY-rf-2x2"/>
<outlet property="searchContentsController" destination="S8q-YF-Kt9" id="2RA-rs-GhH"/>
<outlet property="searchResultsDataSource" destination="S8q-YF-Kt9" id="Cdu-go-UBQ"/>
<outlet property="searchResultsDelegate" destination="S8q-YF-Kt9" id="xxe-xE-sFM"/>
</connections>
</searchDisplayController>
</objects>
<point key="canvasLocation" x="2041" y="226"/>
</scene>
@@ -1158,7 +1149,8 @@ Note that this feature requires you enable the Save Password option and have pur
<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" minimumZoomScale="0.0" maximumZoomScale="0.0" keyboardDismissMode="interactive" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="aXw-tn-8Sj" userLabel="Password Collection">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" sectionInsetReference="safeArea" id="Mv1-29-TWx">
<edgeInsets key="layoutMargins" top="100" left="0.0" bottom="0.0" right="0.0"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" sectionInsetReference="layoutMargins" id="Mv1-29-TWx">
<size key="itemSize" width="355" height="100"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
@@ -1166,7 +1158,7 @@ Note that this feature requires you enable the Save Password option and have pur
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPSiteCell" id="W2g-yv-V3V" customClass="MPSiteCell">
<rect key="frame" x="29.5" y="10" width="355" height="100"/>
<rect key="frame" x="29.5" y="110" width="355" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="355" height="100"/>
@@ -2249,7 +2241,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
<dataDetectorType key="dataDetectorTypes" link="YES"/>
</textView>
<toolbar contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="WmH-JB-jp2">
<rect key="frame" x="0.0" y="764" width="414" height="49"/>
<rect key="frame" x="0.0" y="769" width="414" height="44"/>
<items>
<barButtonItem systemItem="compose" id="BSV-3i-01h">
<connections>
@@ -2264,7 +2256,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
<barButtonItem systemItem="flexibleSpace" id="Lp4-ss-KxI"/>
<barButtonItem style="plain" id="aMS-HH-mnE">
<segmentedControl key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="lxp-wx-uCy">
<rect key="frame" x="267" y="11" width="127" height="32"/>
<rect key="frame" x="267" y="6" width="127" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<segments>
<segment title="Normal"/>
@@ -2764,7 +2756,7 @@ Invested: 3.7 work hours</string>
<rect key="frame" x="188.5" y="20" width="37" height="37"/>
</activityIndicatorView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Loading products..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NPg-it-juF">
<rect key="frame" x="134.5" y="97" width="145.5" height="25"/>
<rect key="frame" x="134" y="97" width="146" height="25"/>
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@@ -3166,7 +3158,7 @@ Ut in geometria, prima si dederis, danda sunt omnia. Nonne igitur tibi videntur,
<attributes>
<color key="NSBackgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<font key="NSFont" metaFont="controlContent"/>
<font key="NSFont" metaFont="label" size="12"/>
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
</attributes>
</fragment>
@@ -3280,8 +3272,8 @@ Ut in geometria, prima si dederis, danda sunt omnia. Nonne igitur tibi videntur,
</scene>
</scenes>
<inferredMetricsTieBreakers>
<segue reference="k2G-nL-x3l"/>
<segue reference="GZk-I4-JyH"/>
<segue reference="Ql4-wf-T8u"/>
<segue reference="gtb-zE-u9H"/>
</inferredMetricsTieBreakers>
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<resources>

View File

@@ -151,7 +151,7 @@ public interface MPAlgorithm {
/**
* The algorithm iterations.
*/
enum Version implements MPAlgorithm {
enum Version implements MPAlgorithm {
/**
* bugs:
@@ -346,7 +346,7 @@ public interface MPAlgorithm {
@Nonnull
@Override
public Version version() {
return MPAlgorithm.Version.V0;
return this;
}
@Nonnull

View File

@@ -20,7 +20,6 @@ package com.lyndir.masterpassword;
import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedInteger;
import com.lyndir.lhunath.opal.system.CodeUtils;
import com.lyndir.lhunath.opal.system.logging.Logger;
import java.util.Arrays;
import java.util.EnumMap;
@@ -56,6 +55,7 @@ public class MPMasterKey {
}
@Override
@SuppressWarnings("deprecation")
protected void finalize()
throws Throwable {