Some usability improvements + apptentive fixes.
[IMPROVED] Make persistence more lazy to avoid UI blocks. [IMPROVED] Use "Master Password" as CFBundleDisplayName at runtime. No home-screen length restrictions there. [FIXED] Inform Apptentive of significant events.
This commit is contained in:
parent
ac14b10752
commit
7d0ea4b3f5
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -6,7 +6,7 @@
|
|||||||
url = git://github.com/futuretap/InAppSettingsKit.git
|
url = git://github.com/futuretap/InAppSettingsKit.git
|
||||||
[submodule "External/iCloudStoreManager"]
|
[submodule "External/iCloudStoreManager"]
|
||||||
path = External/iCloudStoreManager
|
path = External/iCloudStoreManager
|
||||||
url = git://github.com/alekseyn/iCloudStoreManager.git
|
url = git://github.com/lhunath/iCloudStoreManager.git
|
||||||
[submodule "External/apptentive"]
|
[submodule "External/apptentive"]
|
||||||
path = External/apptentive
|
path = External/apptentive
|
||||||
url = git://github.com/apptentive/apptentive-ios.git
|
url = git://github.com/apptentive/apptentive-ios.git
|
||||||
|
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit f92b0b1490e483d1bd4b8b6d1b9482c7ecfd4e44
|
Subproject commit 046dba155843d7a10d5c087e5b1d698ab271df67
|
2
External/iCloudStoreManager
vendored
2
External/iCloudStoreManager
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 6c19d5aa27b07d9a55cd19b003c4383b055b995f
|
Subproject commit 84c718a57d64933e626d3756993fce513ad2bc2a
|
@ -18,6 +18,13 @@
|
|||||||
DA0A1D1215690AD40092735D /* tip_arrow_wood.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */; };
|
DA0A1D1215690AD40092735D /* tip_arrow_wood.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */; };
|
||||||
DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1315690AF30092735D /* Icon-72@2x.png */; };
|
DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1315690AF30092735D /* Icon-72@2x.png */; };
|
||||||
DA0A1D1615690AF40092735D /* Icon-Small-50@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */; };
|
DA0A1D1615690AF40092735D /* Icon-Small-50@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */; };
|
||||||
|
DA30E9CE15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */; };
|
||||||
|
DA30E9CF15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */; };
|
||||||
|
DA30E9D015722ECA00A68B4C /* Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9CD15722ECA00A68B4C /* Pearl.m */; };
|
||||||
|
DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */; };
|
||||||
|
DA30E9D415722EF400A68B4C /* Pearl-UIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */; };
|
||||||
|
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9D515723E6900A68B4C /* PearlLazy.h */; };
|
||||||
|
DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D615723E6900A68B4C /* PearlLazy.m */; };
|
||||||
DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
DA4425CC1557BED40052177D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||||
DA4426001557BF260052177D /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4425F11557BF260052177D /* UbiquityStoreManager.h */; };
|
DA4426001557BF260052177D /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA4425F11557BF260052177D /* UbiquityStoreManager.h */; };
|
||||||
DA4426011557BF260052177D /* UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4425F21557BF260052177D /* UbiquityStoreManager.m */; };
|
DA4426011557BF260052177D /* UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4425F21557BF260052177D /* UbiquityStoreManager.m */; };
|
||||||
@ -925,6 +932,13 @@
|
|||||||
DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tip_arrow_wood.png; path = Resources/Tooltips/tip_arrow_wood.png; sourceTree = SOURCE_ROOT; };
|
DA0A1D0C15690AD40092735D /* tip_arrow_wood.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tip_arrow_wood.png; path = Resources/Tooltips/tip_arrow_wood.png; sourceTree = SOURCE_ROOT; };
|
||||||
DA0A1D1315690AF30092735D /* Icon-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72@2x.png"; sourceTree = "<group>"; };
|
DA0A1D1315690AF30092735D /* Icon-72@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72@2x.png"; sourceTree = "<group>"; };
|
||||||
DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50@2x.png"; sourceTree = "<group>"; };
|
DA0A1D1415690AF40092735D /* Icon-Small-50@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-50@2x.png"; sourceTree = "<group>"; };
|
||||||
|
DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSBundle_PearlMutableInfo.h; sourceTree = "<group>"; };
|
||||||
|
DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSBundle_PearlMutableInfo.m; sourceTree = "<group>"; };
|
||||||
|
DA30E9CD15722ECA00A68B4C /* Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Pearl.m; sourceTree = "<group>"; };
|
||||||
|
DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-Crypto.m"; sourceTree = "<group>"; };
|
||||||
|
DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-UIKit.m"; sourceTree = "<group>"; };
|
||||||
|
DA30E9D515723E6900A68B4C /* PearlLazy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLazy.h; sourceTree = "<group>"; };
|
||||||
|
DA30E9D615723E6900A68B4C /* PearlLazy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLazy.m; sourceTree = "<group>"; };
|
||||||
DA4425CB1557BED40052177D /* libiCloudStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiCloudStoreManager.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
DA4425CB1557BED40052177D /* libiCloudStoreManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiCloudStoreManager.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
DA4425F11557BF260052177D /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = "<group>"; };
|
DA4425F11557BF260052177D /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = "<group>"; };
|
||||||
DA4425F21557BF260052177D /* UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UbiquityStoreManager.m; sourceTree = "<group>"; };
|
DA4425F21557BF260052177D /* UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UbiquityStoreManager.m; sourceTree = "<group>"; };
|
||||||
@ -2892,6 +2906,8 @@
|
|||||||
DAFE45D715039823003ABA7C /* Pearl */ = {
|
DAFE45D715039823003ABA7C /* Pearl */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DA30E9CB15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h */,
|
||||||
|
DA30E9CC15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m */,
|
||||||
DAFE45D815039823003ABA7C /* NSObject_PearlExport.h */,
|
DAFE45D815039823003ABA7C /* NSObject_PearlExport.h */,
|
||||||
DAFE45D915039823003ABA7C /* NSObject_PearlExport.m */,
|
DAFE45D915039823003ABA7C /* NSObject_PearlExport.m */,
|
||||||
DAFE45DA15039823003ABA7C /* NSString_PearlNSArrayFormat.h */,
|
DAFE45DA15039823003ABA7C /* NSString_PearlNSArrayFormat.h */,
|
||||||
@ -2899,6 +2915,7 @@
|
|||||||
DAFE45DC15039823003ABA7C /* NSString_PearlSEL.h */,
|
DAFE45DC15039823003ABA7C /* NSString_PearlSEL.h */,
|
||||||
DAFE45DD15039823003ABA7C /* NSString_PearlSEL.m */,
|
DAFE45DD15039823003ABA7C /* NSString_PearlSEL.m */,
|
||||||
DAFE45DE15039823003ABA7C /* Pearl.h */,
|
DAFE45DE15039823003ABA7C /* Pearl.h */,
|
||||||
|
DA30E9CD15722ECA00A68B4C /* Pearl.m */,
|
||||||
DAFE45DF15039823003ABA7C /* PearlAbstractStrings.h */,
|
DAFE45DF15039823003ABA7C /* PearlAbstractStrings.h */,
|
||||||
DAFE45E015039823003ABA7C /* PearlAbstractStrings.m */,
|
DAFE45E015039823003ABA7C /* PearlAbstractStrings.m */,
|
||||||
DAFE45E315039823003ABA7C /* PearlCodeUtils.h */,
|
DAFE45E315039823003ABA7C /* PearlCodeUtils.h */,
|
||||||
@ -2909,6 +2926,8 @@
|
|||||||
DAFE45E815039823003ABA7C /* PearlDeviceUtils.m */,
|
DAFE45E815039823003ABA7C /* PearlDeviceUtils.m */,
|
||||||
DAFE45E915039823003ABA7C /* PearlInfoPlist.h */,
|
DAFE45E915039823003ABA7C /* PearlInfoPlist.h */,
|
||||||
DAFE45EA15039823003ABA7C /* PearlInfoPlist.m */,
|
DAFE45EA15039823003ABA7C /* PearlInfoPlist.m */,
|
||||||
|
DA30E9D515723E6900A68B4C /* PearlLazy.h */,
|
||||||
|
DA30E9D615723E6900A68B4C /* PearlLazy.m */,
|
||||||
DAFE45EB15039823003ABA7C /* PearlLogger.h */,
|
DAFE45EB15039823003ABA7C /* PearlLogger.h */,
|
||||||
DAFE45EC15039823003ABA7C /* PearlLogger.m */,
|
DAFE45EC15039823003ABA7C /* PearlLogger.m */,
|
||||||
DAFE45ED15039823003ABA7C /* PearlMathUtils.h */,
|
DAFE45ED15039823003ABA7C /* PearlMathUtils.h */,
|
||||||
@ -2940,6 +2959,7 @@
|
|||||||
children = (
|
children = (
|
||||||
DA79A9BB1557DB6F00BAA07A /* libscryptenc-ios.a */,
|
DA79A9BB1557DB6F00BAA07A /* libscryptenc-ios.a */,
|
||||||
DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */,
|
DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */,
|
||||||
|
DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */,
|
||||||
DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */,
|
DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */,
|
||||||
DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */,
|
DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */,
|
||||||
DAFE460015039823003ABA7C /* PearlKeyChain.h */,
|
DAFE460015039823003ABA7C /* PearlKeyChain.h */,
|
||||||
@ -2959,6 +2979,7 @@
|
|||||||
children = (
|
children = (
|
||||||
DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */,
|
DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */,
|
||||||
DAFE460915039823003ABA7C /* Pearl-UIKit.h */,
|
DAFE460915039823003ABA7C /* Pearl-UIKit.h */,
|
||||||
|
DA30E9D315722EF400A68B4C /* Pearl-UIKit.m */,
|
||||||
DAFE460A15039823003ABA7C /* PearlAlert.h */,
|
DAFE460A15039823003ABA7C /* PearlAlert.h */,
|
||||||
DAFE460B15039823003ABA7C /* PearlAlert.m */,
|
DAFE460B15039823003ABA7C /* PearlAlert.m */,
|
||||||
DAFE4A60150399FF003ABA7C /* PearlAppDelegate.m */,
|
DAFE4A60150399FF003ABA7C /* PearlAppDelegate.m */,
|
||||||
@ -3094,6 +3115,8 @@
|
|||||||
DAFE4A5615039824003ABA7C /* PearlWebViewController.h in Headers */,
|
DAFE4A5615039824003ABA7C /* PearlWebViewController.h in Headers */,
|
||||||
DAFE4A5815039824003ABA7C /* UIImage_PearlScaling.h in Headers */,
|
DAFE4A5815039824003ABA7C /* UIImage_PearlScaling.h in Headers */,
|
||||||
DAFE4A63150399FF003ABA7C /* PearlAppDelegate.h in Headers */,
|
DAFE4A63150399FF003ABA7C /* PearlAppDelegate.h in Headers */,
|
||||||
|
DA30E9CE15722ECA00A68B4C /* NSBundle_PearlMutableInfo.h in Headers */,
|
||||||
|
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -4141,6 +4164,11 @@
|
|||||||
DAFE4A5715039824003ABA7C /* PearlWebViewController.m in Sources */,
|
DAFE4A5715039824003ABA7C /* PearlWebViewController.m in Sources */,
|
||||||
DAFE4A5915039824003ABA7C /* UIImage_PearlScaling.m in Sources */,
|
DAFE4A5915039824003ABA7C /* UIImage_PearlScaling.m in Sources */,
|
||||||
DAFE4A62150399FF003ABA7C /* PearlAppDelegate.m in Sources */,
|
DAFE4A62150399FF003ABA7C /* PearlAppDelegate.m in Sources */,
|
||||||
|
DA30E9CF15722ECA00A68B4C /* NSBundle_PearlMutableInfo.m in Sources */,
|
||||||
|
DA30E9D015722ECA00A68B4C /* Pearl.m in Sources */,
|
||||||
|
DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */,
|
||||||
|
DA30E9D415722EF400A68B4C /* Pearl-UIKit.m in Sources */,
|
||||||
|
DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -63,14 +63,23 @@
|
|||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
savedToolIdentifier = ""
|
savedToolIdentifier = ""
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
buildConfiguration = "Production"
|
buildConfiguration = "AppStore"
|
||||||
debugDocumentVersioning = "YES">
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||||
|
BuildableName = "MasterPassword.app"
|
||||||
|
BlueprintName = "MasterPassword"
|
||||||
|
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
</ProfileAction>
|
</ProfileAction>
|
||||||
<AnalyzeAction
|
<AnalyzeAction
|
||||||
buildConfiguration = "Debug">
|
buildConfiguration = "Debug">
|
||||||
</AnalyzeAction>
|
</AnalyzeAction>
|
||||||
<ArchiveAction
|
<ArchiveAction
|
||||||
buildConfiguration = "Production"
|
buildConfiguration = "AppStore"
|
||||||
revealArchiveInOrganizer = "YES">
|
revealArchiveInOrganizer = "YES">
|
||||||
</ArchiveAction>
|
</ArchiveAction>
|
||||||
</Scheme>
|
</Scheme>
|
||||||
|
@ -42,28 +42,37 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
if (managedObjectContext)
|
if (managedObjectContext)
|
||||||
return managedObjectContext;
|
return managedObjectContext;
|
||||||
|
|
||||||
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
return [PearlLazy lazyObjectLoadedFrom:^id{
|
||||||
assert(coordinator);
|
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
||||||
|
assert(coordinator);
|
||||||
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
|
|
||||||
[managedObjectContext performBlockAndWait:^{
|
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
|
||||||
managedObjectContext.persistentStoreCoordinator = coordinator;
|
[managedObjectContext performBlockAndWait:^{
|
||||||
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
|
managedObjectContext.persistentStoreCoordinator = coordinator;
|
||||||
|
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
|
||||||
|
}];
|
||||||
|
|
||||||
|
return managedObjectContext;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return managedObjectContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
|
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
|
||||||
|
|
||||||
|
// Start loading the store.
|
||||||
|
[self storeManager];
|
||||||
|
|
||||||
// Wait until the storeManager is ready.
|
return [PearlLazy lazyObjectLoadedFrom:^id{
|
||||||
for(__block BOOL isReady = [self storeManager].isReady; !isReady;)
|
// Wait until the storeManager is ready.
|
||||||
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
for(__block BOOL isReady = [self storeManager].isReady; !isReady;) {
|
||||||
isReady = [self storeManager].isReady;
|
[NSThread sleepForTimeInterval:0.1];
|
||||||
});
|
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
|
isReady = [self storeManager].isReady;
|
||||||
assert([self storeManager].isReady);
|
});
|
||||||
return [self storeManager].persistentStoreCoordinator;
|
}
|
||||||
|
|
||||||
|
assert([self storeManager].isReady);
|
||||||
|
return [self storeManager].persistentStoreCoordinator;
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UbiquityStoreManager *)storeManager {
|
- (UbiquityStoreManager *)storeManager {
|
||||||
|
@ -148,6 +148,8 @@
|
|||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
|
|
||||||
|
[[[NSBundle mainBundle] mutableLocalizedInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
@try {
|
@try {
|
||||||
@ -207,20 +209,39 @@
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
@try {
|
@try {
|
||||||
NSString *apptentiveAPIKey = [self apptentiveAPIKey];
|
NSString *apptentiveAPIKey = [self apptentiveAPIKey];
|
||||||
if ([apptentiveAPIKey length]) {
|
if ([apptentiveAPIKey length]) {
|
||||||
dbg(@"Initializing Apptentive");
|
dbg(@"Initializing Apptentive");
|
||||||
|
|
||||||
ATConnect *connection = [ATConnect sharedConnection];
|
ATConnect *connection = [ATConnect sharedConnection];
|
||||||
connection.shouldTakeScreenshot = NO;
|
[connection setApiKey:apptentiveAPIKey];
|
||||||
connection.apiKey = apptentiveAPIKey;
|
[connection setShouldTakeScreenshot:NO];
|
||||||
|
[connection addAdditionalInfoToFeedback:[PearlInfoPlist get].CFBundleVersion withKey:@"CFBundleVersion"];
|
||||||
|
|
||||||
|
ATAppRatingFlow *ratingsFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:nil queue:nil
|
||||||
|
usingBlock:^(NSNotification *note) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[ratingsFlow appDidEnterForeground:YES
|
||||||
|
viewController:self.navigationController];
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserverForName:MPNotificationKeySet object:nil queue:nil
|
||||||
|
usingBlock:^(NSNotification *note) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[ratingsFlow userDidPerformSignificantEvent:YES
|
||||||
|
viewController:self.navigationController];
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
[ratingsFlow appDidLaunch:YES viewController:self.navigationController];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@catch (NSException *exception) {
|
@catch (NSException *exception) {
|
||||||
err(@"Apptentive: %@", exception);
|
err(@"Apptentive: %@", exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
UIImage *navBarImage = [[UIImage imageNamed:@"ui_navbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
|
UIImage *navBarImage = [[UIImage imageNamed:@"ui_navbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)];
|
||||||
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];
|
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];
|
||||||
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsLandscapePhone];
|
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsLandscapePhone];
|
||||||
@ -288,19 +309,11 @@
|
|||||||
@"https://youtrack.lyndir.com\n"
|
@"https://youtrack.lyndir.com\n"
|
||||||
viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil
|
viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil
|
||||||
cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
||||||
#else
|
|
||||||
@try {
|
|
||||||
ATAppRatingFlow *sharedFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID];
|
|
||||||
[sharedFlow appDidLaunch:YES viewController:self.navigationController];
|
|
||||||
}
|
|
||||||
@catch (NSException *exception) {
|
|
||||||
err(@"Apptentive: %@", exception);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:NO
|
[[UIApplication sharedApplication] setStatusBarHidden:NO
|
||||||
withAnimation:UIStatusBarAnimationSlide];
|
withAnimation:UIStatusBarAnimationSlide];
|
||||||
|
|
||||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,9 +391,6 @@
|
|||||||
|
|
||||||
[TestFlight passCheckpoint:MPTestFlightCheckpointActivated];
|
[TestFlight passCheckpoint:MPTestFlightCheckpointActivated];
|
||||||
|
|
||||||
ATAppRatingFlow *sharedFlow = [ATAppRatingFlow sharedRatingFlowWithAppID:[PearlConfig get].iTunesID];
|
|
||||||
[sharedFlow appDidEnterForeground:YES viewController:self.navigationController];
|
|
||||||
|
|
||||||
[super applicationDidBecomeActive:application];
|
[super applicationDidBecomeActive:application];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,7 +494,7 @@
|
|||||||
cancelTitle:[PearlStrings get].commonButtonThanks otherTitles:nil];
|
cancelTitle:[PearlStrings get].commonButtonThanks otherTitles:nil];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MPConfig get].iCloudDecided = [NSNumber numberWithBool:YES];
|
[MPConfig get].iCloudDecided = [NSNumber numberWithBool:YES];
|
||||||
if (buttonIndex == [alert cancelButtonIndex])
|
if (buttonIndex == [alert cancelButtonIndex])
|
||||||
return;
|
return;
|
||||||
@ -541,7 +551,7 @@
|
|||||||
static NSDictionary *apptentiveInfo = nil;
|
static NSDictionary *apptentiveInfo = nil;
|
||||||
if (apptentiveInfo == nil)
|
if (apptentiveInfo == nil)
|
||||||
apptentiveInfo = [[NSDictionary alloc] initWithContentsOfURL:
|
apptentiveInfo = [[NSDictionary alloc] initWithContentsOfURL:
|
||||||
[[NSBundle mainBundle] URLForResource:@"Apptentive" withExtension:@"plist"]];
|
[[NSBundle mainBundle] URLForResource:@"Apptentive" withExtension:@"plist"]];
|
||||||
|
|
||||||
return apptentiveInfo;
|
return apptentiveInfo;
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,6 @@
|
|||||||
|
|
||||||
- (void)updateAnimated:(BOOL)animated {
|
- (void)updateAnimated:(BOOL)animated {
|
||||||
|
|
||||||
[[MPAppDelegate get] saveContext];
|
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if (animated)
|
if (animated)
|
||||||
[UIView animateWithDuration:0.3f animations:^{
|
[UIView animateWithDuration:0.3f animations:^{
|
||||||
@ -352,6 +350,7 @@
|
|||||||
NSString *oldPassword = [self.activeElement.content description];
|
NSString *oldPassword = [self.activeElement.content description];
|
||||||
task();
|
task();
|
||||||
NSString *newPassword = [self.activeElement.content description];
|
NSString *newPassword = [self.activeElement.content description];
|
||||||
|
[[MPAppDelegate get] saveContext];
|
||||||
[self updateAnimated:YES];
|
[self updateAnimated:YES];
|
||||||
|
|
||||||
// Show new and old password.
|
// Show new and old password.
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
@interface MPSearchDelegate (Private)
|
@interface MPSearchDelegate (Private)
|
||||||
|
|
||||||
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath;
|
- (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath;
|
||||||
- (void)update;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@ -38,10 +37,14 @@
|
|||||||
|
|
||||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]];
|
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]];
|
||||||
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
|
self.fetchedResultsController = [PearlLazy lazyObjectLoadedFrom:^id{
|
||||||
managedObjectContext:[MPAppDelegate managedObjectContext]
|
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
|
||||||
sectionNameKeyPath:nil cacheName:nil];
|
managedObjectContext:[MPAppDelegate managedObjectContext]
|
||||||
self.fetchedResultsController.delegate = self;
|
sectionNameKeyPath:nil cacheName:nil];
|
||||||
|
controller.delegate = self;
|
||||||
|
|
||||||
|
return controller;
|
||||||
|
}];
|
||||||
|
|
||||||
self.tipView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 170)];
|
self.tipView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 170)];
|
||||||
self.tipView.textAlignment = UITextAlignmentCenter;
|
self.tipView.textAlignment = UITextAlignmentCenter;
|
||||||
@ -123,12 +126,8 @@
|
|||||||
|
|
||||||
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
|
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
|
||||||
|
|
||||||
[self update];
|
if (!controller.active)
|
||||||
|
return NO;
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)update {
|
|
||||||
|
|
||||||
assert(self.query);
|
assert(self.query);
|
||||||
|
|
||||||
@ -138,7 +137,6 @@
|
|||||||
NSError *error;
|
NSError *error;
|
||||||
if (![self.fetchedResultsController performFetch:&error])
|
if (![self.fetchedResultsController performFetch:&error])
|
||||||
err(@"Couldn't fetch elements: %@", error);
|
err(@"Couldn't fetch elements: %@", error);
|
||||||
[self.searchDisplayController.searchResultsTableView reloadData];
|
|
||||||
|
|
||||||
NSArray *subviews = self.searchDisplayController.searchBar.superview.subviews;
|
NSArray *subviews = self.searchDisplayController.searchBar.superview.subviews;
|
||||||
NSUInteger overlayIndex = [subviews indexOfObject:self.searchDisplayController.searchBar] + 1;
|
NSUInteger overlayIndex = [subviews indexOfObject:self.searchDisplayController.searchBar] + 1;
|
||||||
@ -149,6 +147,8 @@
|
|||||||
[self.tipView removeFromSuperview];
|
[self.tipView removeFromSuperview];
|
||||||
[overlay addSubview:self.tipView];
|
[overlay addSubview:self.tipView];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See MP-14, also crashes easily on internal assertions etc..
|
// See MP-14, also crashes easily on internal assertions etc..
|
||||||
|
@ -152,73 +152,69 @@ typedef enum {
|
|||||||
|
|
||||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
||||||
|
|
||||||
|
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
||||||
|
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||||
|
rotate.fromValue = [NSNumber numberWithFloat:0];
|
||||||
|
rotate.toValue = [NSNumber numberWithFloat:2 * M_PI];
|
||||||
|
rotate.repeatCount = MAXFLOAT;
|
||||||
|
rotate.duration = 3.0;
|
||||||
|
|
||||||
|
[self.spinner.layer removeAllAnimations];
|
||||||
|
[self.spinner.layer addAnimation:rotate forKey:@"transform"];
|
||||||
|
|
||||||
|
[UIView animateWithDuration:0.3f animations:^{
|
||||||
|
self.spinner.alpha = 1.0f;
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self showMessage:@"Checking password..." state:MPLockscreenProgress];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
@try {
|
BOOL unlocked = [[MPAppDelegate get] tryMasterPassword:textField.text];
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
if (unlocked) {
|
||||||
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
[self showMessage:@"Success!" state:MPLockscreenSuccess];
|
||||||
rotate.fromValue = [NSNumber numberWithFloat:0];
|
|
||||||
rotate.toValue = [NSNumber numberWithFloat:2 * M_PI];
|
|
||||||
rotate.repeatCount = MAXFLOAT;
|
|
||||||
rotate.duration = 3.0;
|
|
||||||
|
|
||||||
[self.spinner.layer removeAllAnimations];
|
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||||
[self.spinner.layer addAnimation:rotate forKey:@"transform"];
|
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"keyID == %@", [MPAppDelegate get].keyID];
|
||||||
|
fetchRequest.fetchLimit = 1;
|
||||||
[UIView animateWithDuration:0.3f animations:^{
|
BOOL keyIDHasElements = [[[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil] count] > 0;
|
||||||
self.spinner.alpha = 1.0f;
|
if (keyIDHasElements)
|
||||||
}];
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long)(NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{
|
||||||
|
[self dismissModalViewControllerAnimated:YES];
|
||||||
[self showMessage:@"Checking password..." state:MPLockscreenProgress];
|
});
|
||||||
});
|
else {
|
||||||
|
[PearlAlert showAlertWithTitle:@"New Master Password"
|
||||||
if ([[MPAppDelegate get] tryMasterPassword:textField.text])
|
message:
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
@"Please confirm the spelling of this new master password."
|
||||||
[self showMessage:@"Success!" state:MPLockscreenSuccess];
|
viewStyle:UIAlertViewStyleSecureTextInput
|
||||||
|
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
if (buttonIndex == [alert cancelButtonIndex]) {
|
||||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"keyID == %@", [MPAppDelegate get].keyID];
|
[[MPAppDelegate get] updateKey:nil];
|
||||||
fetchRequest.fetchLimit = 1;
|
return;
|
||||||
BOOL keyIDHasElements = [[[MPAppDelegate managedObjectContext] executeFetchRequest:fetchRequest error:nil] count] > 0;
|
|
||||||
if (keyIDHasElements)
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long)(NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{
|
|
||||||
[self dismissModalViewControllerAnimated:YES];
|
|
||||||
});
|
|
||||||
else {
|
|
||||||
[PearlAlert showAlertWithTitle:@"New Master Password"
|
|
||||||
message:
|
|
||||||
@"Please confirm the spelling of this new master password."
|
|
||||||
viewStyle:UIAlertViewStyleSecureTextInput
|
|
||||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
|
||||||
if (buttonIndex == [alert cancelButtonIndex]) {
|
|
||||||
[[MPAppDelegate get] updateKey:nil];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (![[alert textFieldAtIndex:0].text isEqualToString:textField.text]) {
|
|
||||||
[PearlAlert showAlertWithTitle:@"Incorrect Master Password"
|
|
||||||
message:
|
|
||||||
@"The password you entered doesn't match with the master password you tried to use. "
|
|
||||||
@"You've probably mistyped one of them.\n\n"
|
|
||||||
@"Give it another try."
|
|
||||||
viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil
|
|
||||||
cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[self dismissModalViewControllerAnimated:YES];
|
|
||||||
}
|
}
|
||||||
cancelTitle:[PearlStrings get].commonButtonCancel
|
if (![[alert textFieldAtIndex:0].text isEqualToString:textField.text]) {
|
||||||
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
[PearlAlert showAlertWithTitle:@"Incorrect Master Password"
|
||||||
}
|
message:
|
||||||
});
|
@"The password you entered doesn't match with the master password you tried to use. "
|
||||||
else
|
@"You've probably mistyped one of them.\n\n"
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
@"Give it another try."
|
||||||
[self showMessage:@"Not valid." state:MPLockscreenError];
|
viewStyle:UIAlertViewStyleDefault tappedButtonBlock:nil
|
||||||
[UIView animateWithDuration:0.5f animations:^{
|
cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
|
||||||
self.changeMPView.alpha = 1.0f;
|
return;
|
||||||
}];
|
}
|
||||||
});
|
[self dismissModalViewControllerAnimated:YES];
|
||||||
}
|
}
|
||||||
@finally {
|
cancelTitle:[PearlStrings get].commonButtonCancel
|
||||||
|
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
[self showMessage:@"Not valid." state:MPLockscreenError];
|
||||||
|
|
||||||
|
[UIView animateWithDuration:0.5f animations:^{
|
||||||
|
self.changeMPView.alpha = 1.0f;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[UIView animateWithDuration:0.3f animations:^{
|
[UIView animateWithDuration:0.3f animations:^{
|
||||||
self.spinner.alpha = 0.0f;
|
self.spinner.alpha = 0.0f;
|
||||||
@ -226,7 +222,7 @@ typedef enum {
|
|||||||
[self.spinner.layer removeAllAnimations];
|
[self.spinner.layer removeAllAnimations];
|
||||||
}];
|
}];
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
Site/1/img/SolvingThePasswordProblem.png
Normal file
BIN
Site/1/img/SolvingThePasswordProblem.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 376 KiB |
Loading…
Reference in New Issue
Block a user