2
0

Log VC, iCloud toggling, iOS 7 fixes.

[UPDATED]   Show users and sites in cloud stores of log VC.
[ADDED]     Ability to turn off iCloud if corruption happens.
[ADDED]     When switching iCloud on/off, provide user the option to migrate his current sites.
[ADDED]     Ability to get to settings & logs from unlock VC.
This commit is contained in:
Maarten Billemont 2013-09-05 23:52:12 -04:00
parent ab360066e5
commit 0921796136
12 changed files with 387 additions and 237 deletions

@ -1 +1 @@
Subproject commit 3ad873577684c1e98c11cc081200e9d0402ad3b7 Subproject commit fcc72db0d54cd181f27b71e81901fc66958d71bf

@ -1 +1 @@
Subproject commit 77327f4adc7ca9dbca1a1f3e632d1e95c9ce7e56 Subproject commit ebc094f4c160f8aa3ebbe3f760fbf734b58bc5e6

View File

@ -63,9 +63,9 @@
return; return;
switchCloudStoreProgress = [PearlAlert showActivityWithTitle:@"Enumerating Stores"]; switchCloudStoreProgress = [PearlAlert showActivityWithTitle:@"Enumerating Stores"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
[self switchCloudStore]; [self switchCloudStore];
}); } );
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil]; } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil];
} }
} cancelTitle:[PearlStrings get].commonButtonCancel } cancelTitle:[PearlStrings get].commonButtonCancel
@ -75,39 +75,88 @@
- (void)switchCloudStore { - (void)switchCloudStore {
NSError *error = nil; NSError *error = nil;
NSURL *cloudStoreDirectory = [[MPiOSAppDelegate get].storeManager URLForCloudStoreDirectory];
NSURL *cloudContentDirectory = [[MPiOSAppDelegate get].storeManager URLForCloudContentDirectory]; NSURL *cloudContentDirectory = [[MPiOSAppDelegate get].storeManager URLForCloudContentDirectory];
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:cloudContentDirectory includingPropertiesForKeys:nil NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:cloudContentDirectory includingPropertiesForKeys:nil
options:NSDirectoryEnumerationSkipsHiddenFiles error:&error]; options:NSDirectoryEnumerationSkipsHiddenFiles error:&error];
if (!contents) if (!contents)
err(@"While enumerating cloud contents: %@", error); err(@"While enumerating cloud contents: %@", error);
NSMutableArray *contentNames = [NSMutableArray arrayWithCapacity:[contents count]]; BOOL directory;
BOOL directory = NO; NSMutableDictionary *stores = [NSMutableDictionary dictionaryWithCapacity:[contents count]];
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *storePSC = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSFetchRequest *usersFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
NSFetchRequest *sitesFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
for (NSURL *content in contents) for (NSURL *content in contents)
if ([[NSFileManager defaultManager] fileExistsAtPath:content.path isDirectory:&directory] && directory) if ([[NSFileManager defaultManager] fileExistsAtPath:content.path isDirectory:&directory] && directory) {
[contentNames addObject:[content lastPathComponent]]; NSString *contentString = [content lastPathComponent];
NSUInteger lastDash = [contentString rangeOfString:@"-" options:NSBackwardsSearch].location;
NSString *storeDescription = lastDash == NSNotFound? contentString: [contentString substringFromIndex:lastDash + 1];
NSPersistentStore *store = nil;
@try {
NSURL *storeURL = [[cloudStoreDirectory
URLByAppendingPathComponent:[content lastPathComponent] isDirectory:NO]
URLByAppendingPathExtension:@"sqlite"];
if (!(store = [storePSC addPersistentStoreWithType:NSSQLiteStoreType configuration:nil
URL:storeURL options:@{
NSPersistentStoreUbiquitousContentNameKey : [[MPiOSAppDelegate get].storeManager valueForKey:@"contentName"],
NSPersistentStoreUbiquitousContentURLKey : content,
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreFileProtectionKey : NSFileProtectionComplete
} error:&error])) {
wrn(@"Couldn't describe store opening %@: %@", [content lastPathComponent], error);
continue;
}
NSUInteger userCount, siteCount;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.persistentStoreCoordinator = storePSC;
if ((userCount = [moc countForFetchRequest:usersFetchRequest error:&error]) == NSNotFound) {
wrn(@"Couldn't describe store userCount %@: %@", [content lastPathComponent], error);
continue;
}
if ((siteCount = [moc countForFetchRequest:sitesFetchRequest error:&error]) == NSNotFound) {
wrn(@"Couldn't describe store siteCount %@: %@", [content lastPathComponent], error);
continue;
}
storeDescription = PearlString( @"%@: %dU, %dS", storeDescription, userCount, siteCount );
}
@catch (NSException *exception) {
wrn(@"Couldn't describe store %@: exception %@", [content lastPathComponent], exception);
}
@finally {
if (store) if (![storePSC removePersistentStore:store error:&error])
wrn(@"Couldn't remove store %@: %@", [content lastPathComponent], error);
[stores setObject:storeDescription forKey:[content lastPathComponent]];
}
}
NSString *storeUUID = [[MPiOSAppDelegate get].storeManager valueForKey:@"storeUUID_ThreadSafe"]; NSString *storeUUID = [[MPiOSAppDelegate get].storeManager valueForKey:@"storeUUID_ThreadSafe"];
dispatch_async(dispatch_get_main_queue(), ^{ NSUInteger lastDash = [storeUUID rangeOfString:@"-" options:NSBackwardsSearch].location;
NSString *title = PearlString( @"Current: %@", lastDash == NSNotFound? storeUUID: [storeUUID substringFromIndex:lastDash + 1] );
dispatch_async( dispatch_get_main_queue(), ^{
[switchCloudStoreProgress cancelAlertAnimated:YES]; [switchCloudStoreProgress cancelAlertAnimated:YES];
[PearlSheet showSheetWithTitle:storeUUID NSArray *storeUUIDs = [stores allKeys];
viewStyle:UIActionSheetStyleAutomatic [PearlSheet showSheetWithTitle:title viewStyle:UIActionSheetStyleAutomatic
initSheet:^(UIActionSheet *sheet) { initSheet:^(UIActionSheet *sheet) {
for (NSString *contentName in contentNames) { for (NSString *contentName in storeUUIDs)
[sheet addButtonWithTitle:contentName]; [sheet addButtonWithTitle:[stores objectForKey:contentName]];
}
} }
tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
if (buttonIndex == sheet.cancelButtonIndex) if (buttonIndex == sheet.cancelButtonIndex)
return; return;
[[MPiOSAppDelegate get].storeManager setValue:[contentNames objectAtIndex:(unsigned)buttonIndex] forKey:@"storeUUID"]; [[MPiOSAppDelegate get].storeManager setValue:[storeUUIDs objectAtIndex:(unsigned)buttonIndex]
forKey:@"storeUUID"];
[[MPiOSAppDelegate get].storeManager reloadStore]; [[MPiOSAppDelegate get].storeManager reloadStore];
[[MPiOSAppDelegate get] signOutAnimated:YES]; [[MPiOSAppDelegate get] signOutAnimated:YES];
} }
cancelTitle:[PearlStrings get].commonButtonCancel destructiveTitle:nil otherTitles:nil]; cancelTitle:[PearlStrings get].commonButtonCancel destructiveTitle:nil otherTitles:nil];
}); } );
} }
- (IBAction)toggleLevelControl:(UISegmentedControl *)sender { - (IBAction)toggleLevelControl:(UISegmentedControl *)sender {

View File

@ -42,7 +42,7 @@
if (self.cloudSwitch) { if (self.cloudSwitch) {
[MPiOSConfig get].iCloudDecided = @YES; [MPiOSConfig get].iCloudDecided = @YES;
[MPiOSAppDelegate get].storeManager.cloudEnabled = self.cloudSwitch.on; [MPiOSConfig get].iCloudEnabled = @(self.cloudSwitch.on);
} }
if (self.rememberLoginSwitch) if (self.rememberLoginSwitch)
[MPiOSConfig get].rememberLogin = @(self.rememberLoginSwitch.on); [MPiOSConfig get].rememberLogin = @(self.rememberLoginSwitch.on);

View File

@ -37,15 +37,14 @@
@property(weak, nonatomic) IBOutlet UIButton *emergencyPassword; @property(weak, nonatomic) IBOutlet UIButton *emergencyPassword;
@property(weak, nonatomic) IBOutlet UIView *emergencyContentTipContainer; @property(weak, nonatomic) IBOutlet UIView *emergencyContentTipContainer;
@property(nonatomic, strong) UIColor *avatarShadowColor;
- (IBAction)targetedUserAction:(UILongPressGestureRecognizer *)sender; - (IBAction)targetedUserAction:(UILongPressGestureRecognizer *)sender;
- (IBAction)facebook:(UIButton *)sender; - (IBAction)facebook:(id)sender;
- (IBAction)twitter:(UIButton *)sender; - (IBAction)twitter:(id)sender;
- (IBAction)google:(UIButton *)sender; - (IBAction)google:(id)sender;
- (IBAction)mail:(UIButton *)sender; - (IBAction)mail:(id)sender;
- (IBAction)add:(UIButton *)sender; - (IBAction)add:(id)sender;
- (IBAction)emergencyClose:(UIButton *)sender; - (IBAction)emergencyOpen:(id)sender;
- (IBAction)emergencyCopy:(UIButton *)sender; - (IBAction)emergencyClose:(id)sender;
- (IBAction)emergencyCopy:(id)sender;
@end @end

View File

@ -243,12 +243,17 @@
inf(@"Lock screen will disappear"); inf(@"Lock screen will disappear");
[self emergencyCloseAnimated:animated]; [self emergencyCloseAnimated:animated];
[self.marqueeTipTimer invalidate]; [self.marqueeTipTimer invalidate];
[super viewWillDisappear:animated]; [super viewWillDisappear:animated];
} }
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"MP_Settings"])
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
- (BOOL)prefersStatusBarHidden { - (BOOL)prefersStatusBarHidden {
return YES; return YES;
@ -266,29 +271,8 @@
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (motion == UIEventSubtypeMotionShake) { if (motion == UIEventSubtypeMotionShake)
MPCheckpoint( MPCheckpointEmergencyGenerator, nil ); [self emergencyOpenAnimated:YES];
[[self.view findFirstResponderInHierarchy] resignFirstResponder];
self.emergencyGeneratorContainer.alpha = 0;
self.emergencyGeneratorContainer.hidden = NO;
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
self.emergencyGeneratorContainer.frame.origin.x - 100 );
[UIView animateWithDuration:0.3 animations:^{
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
self.emergencyGeneratorContainer.frame.origin.x + 150 );
self.emergencyGeneratorContainer.alpha = 1;
} completion:^(BOOL finished) {
if (!finished)
return;
[self.emergencyName becomeFirstResponder];
[UIView animateWithDuration:0.2 animations:^{
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
self.emergencyGeneratorContainer.frame.origin.x - 50 );
}];
}];
}
} }
- (void)marqueeTip { - (void)marqueeTip {
@ -518,7 +502,6 @@
self.nameLabel.center = CGPointMake( 160, 94 ); self.nameLabel.center = CGPointMake( 160, 94 );
self.nameLabel.backgroundColor = [UIColor blackColor]; self.nameLabel.backgroundColor = [UIColor blackColor];
self.oldNameLabel.center = self.nameLabel.center; self.oldNameLabel.center = self.nameLabel.center;
self.avatarShadowColor = [UIColor whiteColor];
} }
else if (!selectedUser && self.passwordView.alpha == 1) { else if (!selectedUser && self.passwordView.alpha == 1) {
// User was just deselected. // User was just deselected.
@ -529,7 +512,6 @@
self.nameLabel.center = CGPointMake( 160, 296 ); self.nameLabel.center = CGPointMake( 160, 296 );
self.nameLabel.backgroundColor = [UIColor clearColor]; self.nameLabel.backgroundColor = [UIColor clearColor];
self.oldNameLabel.center = self.nameLabel.center; self.oldNameLabel.center = self.nameLabel.center;
self.avatarShadowColor = [UIColor lightGrayColor];
} }
// Lay out the word wall. // Lay out the word wall.
@ -913,12 +895,20 @@
}]; }];
} }
- (IBAction)emergencyClose:(UIButton *)sender { - (IBAction)emergencyOpen:(id)sender {
if ([sender isKindOfClass:[UIGestureRecognizer class]] && ((UIGestureRecognizer *)sender).state != UIGestureRecognizerStateBegan)
return;
[self emergencyOpenAnimated:YES];
}
- (IBAction)emergencyClose:(id)sender {
[self emergencyCloseAnimated:YES]; [self emergencyCloseAnimated:YES];
} }
- (IBAction)emergencyCopy:(UIButton *)sender { - (IBAction)emergencyCopy:(id)sender {
inf(@"Copying emergency password for: %@", self.emergencyName.text); inf(@"Copying emergency password for: %@", self.emergencyName.text);
[UIPasteboard generalPasteboard].string = [self.emergencyPassword titleForState:UIControlStateNormal]; [UIPasteboard generalPasteboard].string = [self.emergencyPassword titleForState:UIControlStateNormal];
@ -943,6 +933,38 @@
} ); } );
} }
- (void)emergencyOpenAnimated:(BOOL)animated {
[[self.emergencyGeneratorContainer findFirstResponderInHierarchy] resignFirstResponder];
if (animated) {
self.emergencyGeneratorContainer.alpha = 0;
self.emergencyGeneratorContainer.hidden = NO;
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
self.emergencyGeneratorContainer.frame.origin.x - 100 );
[UIView animateWithDuration:0.2 animations:^{
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
self.emergencyGeneratorContainer.frame.origin.x + 150 );
self.emergencyGeneratorContainer.alpha = 1;
} completion:^(BOOL finished) {
if (finished) {
[self emergencyOpenAnimated:NO];
[UIView animateWithDuration:0.2 animations:^{
self.emergencyGeneratorContainer.frame = CGRectSetX( self.emergencyGeneratorContainer.frame,
self.emergencyGeneratorContainer.frame.origin.x - 50 );
}];
}
}];
return;
}
MPCheckpoint( MPCheckpointEmergencyGenerator, nil );
self.emergencyGeneratorContainer.hidden = NO;
self.emergencyGeneratorContainer.alpha = 1;
[self.emergencyName becomeFirstResponder];
}
- (void)emergencyCloseAnimated:(BOOL)animated { - (void)emergencyCloseAnimated:(BOOL)animated {
[[self.emergencyGeneratorContainer findFirstResponderInHierarchy] resignFirstResponder]; [[self.emergencyGeneratorContainer findFirstResponderInHierarchy] resignFirstResponder];
@ -951,7 +973,8 @@
[UIView animateWithDuration:0.2 animations:^{ [UIView animateWithDuration:0.2 animations:^{
self.emergencyGeneratorContainer.alpha = 0; self.emergencyGeneratorContainer.alpha = 0;
} completion:^(BOOL finished) { } completion:^(BOOL finished) {
[self emergencyCloseAnimated:NO]; if (finished)
[self emergencyCloseAnimated:NO];
}]; }];
return; return;
} }
@ -1043,7 +1066,7 @@
destructiveTitle:@"Delete User" otherTitles:@"Reset Password", nil]; destructiveTitle:@"Delete User" otherTitles:@"Reset Password", nil];
} }
- (IBAction)facebook:(UIButton *)sender { - (IBAction)facebook:(id)sender {
if (![SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) { if (![SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
[PearlAlert showAlertWithTitle:@"Facebook Not Enabled" message:@"To send tweets, configure Facebook from Settings." [PearlAlert showAlertWithTitle:@"Facebook Not Enabled" message:@"To send tweets, configure Facebook from Settings."
@ -1058,7 +1081,7 @@
[self presentViewController:vc animated:YES completion:nil]; [self presentViewController:vc animated:YES completion:nil];
} }
- (IBAction)twitter:(UIButton *)sender { - (IBAction)twitter:(id)sender {
if (![SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) { if (![SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) {
[PearlAlert showAlertWithTitle:@"Twitter Not Enabled" message:@"To send tweets, configure Twitter from Settings." [PearlAlert showAlertWithTitle:@"Twitter Not Enabled" message:@"To send tweets, configure Twitter from Settings."
@ -1073,19 +1096,19 @@
[self presentViewController:vc animated:YES completion:nil]; [self presentViewController:vc animated:YES completion:nil];
} }
- (IBAction)google:(UIButton *)sender { - (IBAction)google:(id)sender {
id<GPPShareBuilder> shareDialog = [[GPPShare sharedInstance] shareDialog]; id<GPPShareBuilder> shareDialog = [[GPPShare sharedInstance] shareDialog];
[[[shareDialog setURLToShare:[NSURL URLWithString:@"http://masterpasswordapp.com"]] [[[shareDialog setURLToShare:[NSURL URLWithString:@"http://masterpasswordapp.com"]]
setPrefillText:@"I've started doing passwords properly thanks to Master Password."] open]; setPrefillText:@"I've started doing passwords properly thanks to Master Password."] open];
} }
- (IBAction)mail:(UIButton *)sender { - (IBAction)mail:(id)sender {
[[MPiOSAppDelegate get] showFeedbackWithLogs:NO forVC:self]; [[MPiOSAppDelegate get] showFeedbackWithLogs:NO forVC:self];
} }
- (IBAction)add:(UIButton *)sender { - (IBAction)add:(id)sender {
[PearlSheet showSheetWithTitle:@"Follow Master Password" viewStyle:UIActionSheetStyleBlackTranslucent [PearlSheet showSheetWithTitle:@"Follow Master Password" viewStyle:UIActionSheetStyleBlackTranslucent
initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {

View File

@ -182,67 +182,12 @@
@try { @try {
[[NSNotificationCenter defaultCenter] addObserverForName:MPCheckConfigNotification object:nil queue:nil usingBlock: [[NSNotificationCenter defaultCenter] addObserverForName:MPCheckConfigNotification object:nil queue:nil usingBlock:
^(NSNotification *note) { ^(NSNotification *note) {
if ([[MPiOSConfig get].sendInfo boolValue]) { [self checkConfig];
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
[PearlLogger get].printLevel = PearlLogLevelInfo;
#ifdef CRASHLYTICS
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].rememberLogin boolValue] forKey:@"rememberLogin"];
[[Crashlytics sharedInstance] setBoolValue:[self storeManager].cloudEnabled forKey:@"iCloud"];
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].iCloudDecided boolValue] forKey:@"iCloudDecided"];
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].sendInfo boolValue] forKey:@"sendInfo"];
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].helpHidden boolValue] forKey:@"helpHidden"];
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].showSetup boolValue] forKey:@"showQuickStart"];
[[Crashlytics sharedInstance] setBoolValue:[[PearlConfig get].firstRun boolValue] forKey:@"firstRun"];
[[Crashlytics sharedInstance] setIntValue:[[PearlConfig get].launchCount intValue] forKey:@"launchCount"];
[[Crashlytics sharedInstance] setBoolValue:[[PearlConfig get].askForReviews boolValue] forKey:@"askForReviews"];
[[Crashlytics sharedInstance]
setIntValue:[[PearlConfig get].reviewAfterLaunches intValue] forKey:@"reviewAfterLaunches"];
[[Crashlytics sharedInstance] setObjectValue:[PearlConfig get].reviewedVersion forKey:@"reviewedVersion"];
#endif
#ifdef TESTFLIGHT_SDK_VERSION
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPConfig get].rememberLogin )
forKey:@"rememberLogin"];
[TestFlight addCustomEnvironmentInformation:PearlStringB( [self storeManager].cloudEnabled )
forKey:@"iCloud"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPConfig get].iCloudDecided )
forKey:@"iCloudDecided"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPiOSConfig get].sendInfo )
forKey:@"sendInfo"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPiOSConfig get].helpHidden )
forKey:@"helpHidden"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPiOSConfig get].showSetup )
forKey:@"showQuickStart"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].firstRun )
forKey:@"firstRun"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].launchCount )
forKey:@"launchCount"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].askForReviews )
forKey:@"askForReviews"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].reviewAfterLaunches )
forKey:@"reviewAfterLaunches"];
[TestFlight addCustomEnvironmentInformation:[PearlConfig get].reviewedVersion
forKey:@"reviewedVersion"];
#endif
MPCheckpoint( MPCheckpointConfig, @{
@"rememberLogin" : @([[MPConfig get].rememberLogin boolValue]),
@"iCloud" : @([self storeManager].cloudEnabled),
@"iCloudDecided" : @([[MPConfig get].iCloudDecided boolValue]),
@"sendInfo" : @([[MPiOSConfig get].sendInfo boolValue]),
@"helpHidden" : @([[MPiOSConfig get].helpHidden boolValue]),
@"showQuickStart" : @([[MPiOSConfig get].showSetup boolValue]),
@"firstRun" : @([[PearlConfig get].firstRun boolValue]),
@"launchCount" : NilToNSNull([PearlConfig get].launchCount),
@"askForReviews" : @([[PearlConfig get].askForReviews boolValue]),
@"reviewAfterLaunches" : NilToNSNull([PearlConfig get].reviewAfterLaunches),
@"reviewedVersion" : NilToNSNull([PearlConfig get].reviewedVersion)
} );
}
}]; }];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserverForName:kIASKAppSettingChanged object:nil queue:nil usingBlock:^(NSNotification *note) { addObserverForName:kIASKAppSettingChanged object:nil queue:nil usingBlock:^(NSNotification *note) {
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:note userInfo:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
object:note userInfo:nil];
}]; }];
#ifdef ADHOC #ifdef ADHOC
@ -447,7 +392,8 @@
- (void)applicationDidBecomeActive:(UIApplication *)application { - (void)applicationDidBecomeActive:(UIApplication *)application {
inf(@"Re-activated"); inf(@"Re-activated");
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:application userInfo:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
object:application userInfo:nil];
#ifdef LOCALYTICS #ifdef LOCALYTICS
[[LocalyticsSession sharedLocalyticsSession] resume]; [[LocalyticsSession sharedLocalyticsSession] resume];
@ -635,17 +581,108 @@
otherTitles:[PearlStrings get].commonButtonContinue, nil]; otherTitles:[PearlStrings get].commonButtonContinue, nil];
} }
#pragma mark - PearlConfigDelegate #pragma mark - PearlConfigDelegate
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value { - (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value {
if (configKey == @selector(traceMode)) { [[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
[PearlLogger get].historyLevel = [[MPiOSConfig get].traceMode boolValue]? PearlLogLevelTrace: PearlLogLevelInfo; object:NSStringFromSelector( configKey ) userInfo:nil];
inf(@"Trace is now: %@", [[MPiOSConfig get].traceMode boolValue]? @"ON": @"OFF"); }
- (void)checkConfig {
// iCloud enabled / disabled
if ([[MPiOSConfig get].iCloudEnabled boolValue] != self.storeManager.cloudEnabled) {
if ([[MPiOSConfig get].iCloudEnabled boolValue])
[self.storeManager setCloudEnabledAndOverwriteCloudWithLocalIfConfirmed:^(void (^setConfirmationAnswer)(BOOL answer)) {
[PearlAlert showAlertWithTitle:@"Keep Sites?"
message:@"You can either revert to your old iCloud sites or overwrite them with your current sites."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
if (buttonIndex == [alert cancelButtonIndex])
setConfirmationAnswer( NO );
if (buttonIndex == [alert firstOtherButtonIndex])
setConfirmationAnswer( YES );
}
cancelTitle:@"Revert" otherTitles:@"Replace iCloud", nil];
}];
else
[self.storeManager setCloudDisabledAndOverwriteLocalWithCloudIfConfirmed:^(void (^setConfirmationAnswer)(BOOL answer)) {
[PearlAlert showAlertWithTitle:@"Keep iCloud Sites?"
message:@"You can either revert to your old sites or overwrite them with your current iCloud sites."
viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
if (buttonIndex == [alert cancelButtonIndex])
setConfirmationAnswer( NO );
if (buttonIndex == [alert firstOtherButtonIndex])
setConfirmationAnswer( YES );
}
cancelTitle:@"Revert" otherTitles:@"Copy iCloud", nil];
}];
} }
[[NSNotificationCenter defaultCenter] // Trace mode
postNotificationName:MPCheckConfigNotification object:NSStringFromSelector( configKey ) userInfo:nil]; [PearlLogger get].historyLevel = [[MPiOSConfig get].traceMode boolValue]? PearlLogLevelTrace: PearlLogLevelInfo;
// Send info
if ([[MPiOSConfig get].sendInfo boolValue]) {
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
[PearlLogger get].printLevel = PearlLogLevelInfo;
#ifdef CRASHLYTICS
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].rememberLogin boolValue] forKey:@"rememberLogin"];
[[Crashlytics sharedInstance] setBoolValue:[self storeManager].cloudEnabled forKey:@"iCloud"];
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].iCloudDecided boolValue] forKey:@"iCloudDecided"];
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].sendInfo boolValue] forKey:@"sendInfo"];
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].helpHidden boolValue] forKey:@"helpHidden"];
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].showSetup boolValue] forKey:@"showQuickStart"];
[[Crashlytics sharedInstance] setBoolValue:[[PearlConfig get].firstRun boolValue] forKey:@"firstRun"];
[[Crashlytics sharedInstance] setIntValue:[[PearlConfig get].launchCount intValue] forKey:@"launchCount"];
[[Crashlytics sharedInstance] setBoolValue:[[PearlConfig get].askForReviews boolValue] forKey:@"askForReviews"];
[[Crashlytics sharedInstance]
setIntValue:[[PearlConfig get].reviewAfterLaunches intValue] forKey:@"reviewAfterLaunches"];
[[Crashlytics sharedInstance] setObjectValue:[PearlConfig get].reviewedVersion forKey:@"reviewedVersion"];
#endif
#ifdef TESTFLIGHT_SDK_VERSION
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPConfig get].rememberLogin )
forKey:@"rememberLogin"];
[TestFlight addCustomEnvironmentInformation:PearlStringB( [self storeManager].cloudEnabled )
forKey:@"iCloud"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPConfig get].iCloudDecided )
forKey:@"iCloudDecided"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPiOSConfig get].sendInfo )
forKey:@"sendInfo"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPiOSConfig get].helpHidden )
forKey:@"helpHidden"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [MPiOSConfig get].showSetup )
forKey:@"showQuickStart"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].firstRun )
forKey:@"firstRun"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].launchCount )
forKey:@"launchCount"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].askForReviews )
forKey:@"askForReviews"];
[TestFlight addCustomEnvironmentInformation:PearlStringNSB( [PearlConfig get].reviewAfterLaunches )
forKey:@"reviewAfterLaunches"];
[TestFlight addCustomEnvironmentInformation:[PearlConfig get].reviewedVersion
forKey:@"reviewedVersion"];
#endif
MPCheckpoint( MPCheckpointConfig, @{
@"rememberLogin" : @([[MPConfig get].rememberLogin boolValue]),
@"iCloud" : @([self storeManager].cloudEnabled),
@"iCloudDecided" : @([[MPConfig get].iCloudDecided boolValue]),
@"sendInfo" : @([[MPiOSConfig get].sendInfo boolValue]),
@"helpHidden" : @([[MPiOSConfig get].helpHidden boolValue]),
@"showQuickStart" : @([[MPiOSConfig get].showSetup boolValue]),
@"firstRun" : @([[PearlConfig get].firstRun boolValue]),
@"launchCount" : NilToNSNull([PearlConfig get].launchCount),
@"askForReviews" : @([[PearlConfig get].askForReviews boolValue]),
@"reviewAfterLaunches" : NilToNSNull([PearlConfig get].reviewAfterLaunches),
@"reviewedVersion" : NilToNSNull([PearlConfig get].reviewedVersion)
} );
}
} }
@ -665,6 +702,7 @@
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didLoadStoreForCoordinator:(NSPersistentStoreCoordinator *)coordinator - (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didLoadStoreForCoordinator:(NSPersistentStoreCoordinator *)coordinator
isCloud:(BOOL)isCloudStore { isCloud:(BOOL)isCloudStore {
[MPiOSConfig get].iCloudEnabled = @(isCloudStore);
[super ubiquityStoreManager:manager didLoadStoreForCoordinator:coordinator isCloud:isCloudStore]; [super ubiquityStoreManager:manager didLoadStoreForCoordinator:coordinator isCloud:isCloudStore];
dispatch_async( dispatch_get_main_queue(), ^{ dispatch_async( dispatch_get_main_queue(), ^{
@ -693,24 +731,27 @@
@"Waiting for your other device to autocorrect the problem..." @"Waiting for your other device to autocorrect the problem..."
initAlert:^(UIAlertView *alert) { initAlert:^(UIAlertView *alert) {
[alert addButtonWithTitle:@"Fix Now"]; [alert addButtonWithTitle:@"Fix Now"];
[alert addButtonWithTitle:@"Turn Off"];
}]; }];
self.handleCloudContentAlert.tappedButtonBlock = ^(UIAlertView *alert, NSInteger buttonIndex) { self.handleCloudContentAlert.tappedButtonBlock = ^(UIAlertView *alert, NSInteger buttonIndex) {
wSelf.fixCloudContentAlert = [PearlAlert showAlertWithTitle:@"Fix iCloud Now" message: if (buttonIndex == [alert firstOtherButtonIndex])
@"This problem can be autocorrected by opening the app on another device where you recently made changes.\n" wSelf.fixCloudContentAlert = [PearlAlert showAlertWithTitle:@"Fix iCloud Now" message:
@"You can correct the problem from this device anyway, but recent changes made on another device might get lost.\n\n" @"This problem can be autocorrected by opening the app on another device where you recently made changes.\n"
@"You can also turn iCloud off and go back to your local sites." @"You can fix the problem from this device anyway, but recent changes from another device might get lost.\n\n"
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock: @"You can also turn iCloud off for now."
^(UIAlertView *alert_, NSInteger buttonIndex_) { viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:
if (buttonIndex_ == alert_.cancelButtonIndex) ^(UIAlertView *alert_, NSInteger buttonIndex_) {
[wSelf showCloudContentAlert]; if (buttonIndex_ == alert_.cancelButtonIndex)
if (buttonIndex_ == [alert_ firstOtherButtonIndex]) [wSelf showCloudContentAlert];
[wSelf.storeManager rebuildCloudContentFromCloudStoreOrLocalStore:YES]; if (buttonIndex_ == [alert_ firstOtherButtonIndex])
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1) [wSelf.storeManager rebuildCloudContentFromCloudStoreOrLocalStore:YES];
wSelf.storeManager.cloudEnabled = NO; if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1)
} [MPiOSConfig get].iCloudEnabled = NO;
cancelTitle:[PearlStrings get].commonButtonBack otherTitles:@"Fix Anyway", } cancelTitle:[PearlStrings get].commonButtonBack
@"Turn Off", nil]; otherTitles:@"Fix Anyway", @"Turn Off", nil];
if (buttonIndex == [alert firstOtherButtonIndex] + 1)
[MPiOSConfig get].iCloudEnabled = NO;
}; };
} }

View File

@ -17,5 +17,6 @@
@property(nonatomic, retain) NSNumber *typeTipShown; @property(nonatomic, retain) NSNumber *typeTipShown;
@property(nonatomic, retain) NSNumber *loginNameTipShown; @property(nonatomic, retain) NSNumber *loginNameTipShown;
@property(nonatomic, retain) NSNumber *traceMode; @property(nonatomic, retain) NSNumber *traceMode;
@property(nonatomic, retain) NSNumber *iCloudEnabled;
@end @end

View File

@ -8,7 +8,7 @@
@implementation MPiOSConfig @implementation MPiOSConfig
@dynamic helpHidden, siteInfoHidden, showSetup, actionsTipShown, typeTipShown, loginNameTipShown, traceMode; @dynamic helpHidden, siteInfoHidden, showSetup, actionsTipShown, typeTipShown, loginNameTipShown, traceMode, iCloudEnabled;
- (id)init { - (id)init {
@ -23,7 +23,8 @@
NSStringFromSelector( @selector(actionsTipShown) ) : @(!self.firstRun), NSStringFromSelector( @selector(actionsTipShown) ) : @(!self.firstRun),
NSStringFromSelector( @selector(typeTipShown) ) : @(!self.firstRun), NSStringFromSelector( @selector(typeTipShown) ) : @(!self.firstRun),
NSStringFromSelector( @selector(loginNameTipShown) ) : @NO, NSStringFromSelector( @selector(loginNameTipShown) ) : @NO,
NSStringFromSelector( @selector(traceMode) ) : @NO NSStringFromSelector( @selector(traceMode) ) : @NO,
NSStringFromSelector( @selector(iCloudEnabled) ) : @YES
}]; }];
return self; return self;

View File

@ -1499,6 +1499,7 @@ You can use the words in the background for inspiration in finding a memorable m
<button opaque="NO" alpha="0.10000000000000001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="vM2-8p-qn7" userLabel="mail"> <button opaque="NO" alpha="0.10000000000000001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="vM2-8p-qn7" userLabel="mail">
<rect key="frame" x="276" y="0.0" width="44" height="44"/> <rect key="frame" x="276" y="0.0" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<gestureRecognizers/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="16"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
<state key="normal" title="✉"> <state key="normal" title="✉">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/> <color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
@ -1509,6 +1510,7 @@ You can use the words in the background for inspiration in finding a memorable m
</state> </state>
<connections> <connections>
<action selector="mail:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="f6b-uF-NNs"/> <action selector="mail:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="f6b-uF-NNs"/>
<outletCollection property="gestureRecognizers" destination="6ew-le-Bbs" appends="YES" id="rBb-Ur-1Cc"/>
</connections> </connections>
</button> </button>
<button opaque="NO" alpha="0.10000000000000001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="2dq-bb-mPl" userLabel="add"> <button opaque="NO" alpha="0.10000000000000001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="2dq-bb-mPl" userLabel="add">
@ -1538,7 +1540,7 @@ You can use the words in the background for inspiration in finding a memorable m
</subviews> </subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view> </view>
<view hidden="YES" alpha="0.30000000000000016" contentMode="scaleToFill" id="KNa-Xb-RuE" userLabel="View - Emergency Generator"> <view alpha="0.30000000000000016" contentMode="scaleToFill" id="KNa-Xb-RuE" userLabel="View - Emergency Generator">
<rect key="frame" x="-100" y="0.0" width="520" height="504"/> <rect key="frame" x="-100" y="0.0" width="520" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
@ -1645,6 +1647,22 @@ You can use the words in the background for inspiration in finding a memorable m
<action selector="emergencyClose:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="U2r-pg-UGB"/> <action selector="emergencyClose:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="U2r-pg-UGB"/>
</connections> </connections>
</button> </button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="Rxb-jY-TFS">
<rect key="frame" x="15" y="1" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" hint="" label="Close"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" image="icon_gears.png">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<segue destination="Vrp-Gl-7qn" kind="push" identifier="MP_Settings" id="hxY-aA-ngI"/>
</connections>
</button>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" hidesWhenStopped="YES" style="whiteLarge" id="3Ax-91-gVM"> <activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" hidesWhenStopped="YES" style="whiteLarge" id="3Ax-91-gVM">
<rect key="frame" x="141" y="324" width="37" height="37"/> <rect key="frame" x="141" y="324" width="37" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
@ -1731,6 +1749,11 @@ You can use the words in the background for inspiration in finding a memorable m
<action selector="targetedUserAction:" destination="Nbn-Rv-sP1" id="mgC-0X-heO"/> <action selector="targetedUserAction:" destination="Nbn-Rv-sP1" id="mgC-0X-heO"/>
</connections> </connections>
</pongPressGestureRecognizer> </pongPressGestureRecognizer>
<pongPressGestureRecognizer allowableMovement="10" minimumPressDuration="0.5" id="6ew-le-Bbs">
<connections>
<action selector="emergencyOpen:" destination="Nbn-Rv-sP1" id="w9I-iB-DcU"/>
</connections>
</pongPressGestureRecognizer>
</objects> </objects>
<point key="canvasLocation" x="455" y="145"/> <point key="canvasLocation" x="455" y="145"/>
</scene> </scene>
@ -2287,7 +2310,13 @@ If you set a custom password, it will be encrypted before it is saved to the clo
<outlet property="delegate" destination="Vrp-Gl-7qn" id="Kcg-1V-uAD"/> <outlet property="delegate" destination="Vrp-Gl-7qn" id="Kcg-1V-uAD"/>
</connections> </connections>
</tableView> </tableView>
<navigationItem key="navigationItem" id="ZbK-tt-Abw"/> <navigationItem key="navigationItem" id="ZbK-tt-Abw">
<barButtonItem key="rightBarButtonItem" title="Logs" id="G5c-pK-nH0">
<connections>
<segue destination="Tx0-mM-kHk" kind="push" id="5Im-dm-qfS"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController> </tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="lBn-RG-JE2" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="lBn-RG-JE2" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects> </objects>
@ -2883,6 +2912,7 @@ However, it means that anyone who finds your device unlocked can do the same.</s
<image name="icon_cancel.png" width="32" height="32"/> <image name="icon_cancel.png" width="32" height="32"/>
<image name="icon_edit.png" width="32" height="32"/> <image name="icon_edit.png" width="32" height="32"/>
<image name="icon_find.png" width="32" height="32"/> <image name="icon_find.png" width="32" height="32"/>
<image name="icon_gears.png" width="32" height="32"/>
<image name="icon_person.png" width="32" height="32"/> <image name="icon_person.png" width="32" height="32"/>
<image name="icon_play.png" width="32" height="32"/> <image name="icon_play.png" width="32" height="32"/>
<image name="icon_plus.png" width="32" height="32"/> <image name="icon_plus.png" width="32" height="32"/>
@ -2918,6 +2948,8 @@ However, it means that anyone who finds your device unlocked can do the same.</s
</simulatedMetricsContainer> </simulatedMetricsContainer>
<inferredMetricsTieBreakers> <inferredMetricsTieBreakers>
<segue reference="swi-5o-hfK"/> <segue reference="swi-5o-hfK"/>
<segue reference="9Bs-cD-ddF"/> <segue reference="hxY-aA-ngI"/>
<segue reference="rWT-Kr-cAs"/>
<segue reference="KIl-ZW-M7G"/>
</inferredMetricsTieBreakers> </inferredMetricsTieBreakers>
</document> </document>

View File

@ -72,6 +72,8 @@
DA6701E016406BB400B61001 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701DF16406BB400B61001 /* AdSupport.framework */; settings = {ATTRIBUTES = (Required, ); }; }; DA6701E016406BB400B61001 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701DF16406BB400B61001 /* AdSupport.framework */; settings = {ATTRIBUTES = (Required, ); }; };
DA672D2F14F92C6B004A189C /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DA672D2E14F92C6B004A189C /* libz.dylib */; }; DA672D2F14F92C6B004A189C /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DA672D2E14F92C6B004A189C /* libz.dylib */; };
DA672D3014F9413D004A189C /* libPearl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC77CAD148291A600BCF976 /* libPearl.a */; }; DA672D3014F9413D004A189C /* libPearl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC77CAD148291A600BCF976 /* libPearl.a */; };
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 */; };
DA829E52159847E0002417D3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; DA829E52159847E0002417D3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DA829E6215984832002417D3 /* libFontReplacer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA829E51159847E0002417D3 /* libFontReplacer.a */; }; DA829E6215984832002417D3 /* libFontReplacer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA829E51159847E0002417D3 /* libFontReplacer.a */; };
DA95D5F214DF0B2C008D1B94 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */; }; DA95D5F214DF0B2C008D1B94 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */; };
@ -3121,6 +3123,7 @@
DABD39041711E29700CF925C /* ui_panel_display@2x.png in Resources */, DABD39041711E29700CF925C /* ui_panel_display@2x.png in Resources */,
DABD391D1711E29700CF925C /* ui_spinner.png in Resources */, DABD391D1711E29700CF925C /* ui_spinner.png in Resources */,
DABD391E1711E29700CF925C /* ui_spinner@2x.png in Resources */, DABD391E1711E29700CF925C /* ui_spinner@2x.png in Resources */,
DA69540617D975D900BF294E /* icon_gears.png in Resources */,
DABD39271711E29700CF925C /* ui_textfield.png in Resources */, DABD39271711E29700CF925C /* ui_textfield.png in Resources */,
DABD39281711E29700CF925C /* ui_textfield@2x.png in Resources */, DABD39281711E29700CF925C /* ui_textfield@2x.png in Resources */,
DABD39291711E29700CF925C /* ui_toolbar_container.png in Resources */, DABD39291711E29700CF925C /* ui_toolbar_container.png in Resources */,
@ -3190,6 +3193,7 @@
DABD3ABD1711E29800CF925C /* icon_play@2x.png in Resources */, DABD3ABD1711E29800CF925C /* icon_play@2x.png in Resources */,
DABD3ABE1711E29800CF925C /* icon_plus.png in Resources */, DABD3ABE1711E29800CF925C /* icon_plus.png in Resources */,
DABD3ABF1711E29800CF925C /* icon_plus@2x.png in Resources */, DABD3ABF1711E29800CF925C /* icon_plus@2x.png in Resources */,
DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */,
DABD3B1C1711E29800CF925C /* icon_up.png in Resources */, DABD3B1C1711E29800CF925C /* icon_up.png in Resources */,
DABD3B1D1711E29800CF925C /* icon_up@2x.png in Resources */, DABD3B1D1711E29800CF925C /* icon_up@2x.png in Resources */,
DABD3B3C1711E29800CF925C /* tip_alert_black.png in Resources */, DABD3B3C1711E29800CF925C /* tip_alert_black.png in Resources */,

View File

@ -1,95 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>PreferenceSpecifiers</key> <key>PreferenceSpecifiers</key>
<array> <array>
<dict> <dict>
<key>FooterText</key> <key>FooterText</key>
<string>Enable this setting to send us carefully anonymized information to help us diagnose and resolve issues you might experience in the future.</string> <string>Enable this setting to send us carefully anonymized information to help us diagnose and resolve issues you might experience in the future.</string>
<key>Title</key> <key>Title</key>
<string></string> <string></string>
<key>Type</key> <key>Type</key>
<string>PSGroupSpecifier</string> <string>PSGroupSpecifier</string>
</dict> </dict>
<dict> <dict>
<key>DefaultValue</key> <key>DefaultValue</key>
<string>[auto]</string> <string>[auto]</string>
<key>Title</key> <key>Title</key>
<string>Version</string> <string>Version</string>
<key>Key</key> <key>Key</key>
<string>unset</string> <string>unset</string>
<key>Type</key> <key>Type</key>
<string>PSTitleValueSpecifier</string> <string>PSTitleValueSpecifier</string>
</dict> </dict>
<dict> <dict>
<key>DefaultValue</key> <key>DefaultValue</key>
<string>[auto]</string> <string>[auto]</string>
<key>Title</key> <key>Title</key>
<string>Build</string> <string>Build</string>
<key>Key</key> <key>Key</key>
<string>unset</string> <string>unset</string>
<key>Type</key> <key>Type</key>
<string>PSTitleValueSpecifier</string> <string>PSTitleValueSpecifier</string>
</dict> </dict>
<dict> <dict>
<key>DefaultValue</key> <key>DefaultValue</key>
<string>[auto]</string> <string>[auto]</string>
<key>Title</key> <key>Title</key>
<string>Copyright</string> <string>Copyright</string>
<key>Type</key> <key>Type</key>
<string>PSTitleValueSpecifier</string> <string>PSTitleValueSpecifier</string>
<key>Key</key> <key>Key</key>
<string>unset</string> <string>unset</string>
</dict> </dict>
<dict> <dict>
<key>Type</key> <key>Type</key>
<string>PSToggleSwitchSpecifier</string> <string>PSToggleSwitchSpecifier</string>
<key>Title</key> <key>Title</key>
<string>Send Diagnostic Info</string> <string>Send Diagnostic Info</string>
<key>Key</key> <key>Key</key>
<string>sendInfo</string> <string>sendInfo</string>
<key>DefaultValue</key> <key>DefaultValue</key>
<false/> <false/>
</dict> </dict>
<dict> <dict>
<key>FooterText</key> <key>FooterText</key>
<string>When enabled, you will not be logged out when switching out of the application. This will help you get to your passwords faster, but when someone finds your device unlocked, they can too.</string> <string>When enabled, you will not be logged out when switching out of the application. This will help you get to your passwords faster, but when someone finds your device unlocked, they can too.</string>
<key>Title</key> <key>Title</key>
<string>Master Password</string> <string>Master Password</string>
<key>Type</key> <key>Type</key>
<string>PSGroupSpecifier</string> <string>PSGroupSpecifier</string>
</dict> </dict>
<dict> <dict>
<key>DefaultValue</key> <key>DefaultValue</key>
<false/> <false/>
<key>Key</key> <key>Key</key>
<string>rememberLogin</string> <string>rememberLogin</string>
<key>Title</key> <key>Title</key>
<string>Stay logged in</string> <string>Stay logged in</string>
<key>Type</key> <key>Type</key>
<string>PSToggleSwitchSpecifier</string> <string>PSToggleSwitchSpecifier</string>
</dict> </dict>
<dict> <dict>
<key>Type</key> <key>Type</key>
<string>PSGroupSpecifier</string> <string>PSGroupSpecifier</string>
<key>Title</key> <key>Title</key>
<string></string> <string></string>
<key>FooterText</key> <key>FooterText</key>
<string>Synchronizes your sites with your other Apple devices. It's also a good way of keeping automatic backups.</string> <string>Synchronizes your sites with your other Apple devices. It&apos;s also a good way of keeping automatic backups.</string>
</dict> </dict>
<dict> <dict>
<key>Type</key> <key>Type</key>
<string>PSToggleSwitchSpecifier</string> <string>PSToggleSwitchSpecifier</string>
<key>Title</key> <key>Title</key>
<string>iCloud</string> <string>iCloud</string>
<key>Key</key> <key>Key</key>
<string>USMCloudEnabledKey</string> <string>iCloudEnabled</string>
<key>DefaultValue</key> <key>DefaultValue</key>
<true/> <true/>
</dict> </dict>
</array> </array>
<key>StringsTable</key> <key>StringsTable</key>
<string>Root</string> <string>Root</string>
</dict> </dict>
</plist> </plist>