Improved feedback + logging.
[REMOVED] Apptentive is now implemented by a standard iOS mail composer window and can optionally include logs. [IMPROVED] Better inf-level logging of what's going on. [AUDITED] Made sure no personal is going out through inf+ levels.
This commit is contained in:
parent
bc2da6a99b
commit
a67d9676ba
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -7,6 +7,3 @@
|
|||||||
[submodule "External/iCloudStoreManager"]
|
[submodule "External/iCloudStoreManager"]
|
||||||
path = External/iCloudStoreManager
|
path = External/iCloudStoreManager
|
||||||
url = git://github.com/lhunath/iCloudStoreManager.git
|
url = git://github.com/lhunath/iCloudStoreManager.git
|
||||||
[submodule "External/apptentive"]
|
|
||||||
path = External/apptentive
|
|
||||||
url = git://github.com/apptentive/apptentive-ios.git
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>API Key</key>
|
|
||||||
<string></string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 0a5a01b8862a3e8d986b23513c5d40ebc152b6fc
|
Subproject commit 82fb855dd9dd61e8a895852b91885c15d27b7c7d
|
1
External/apptentive
vendored
1
External/apptentive
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 3b6635e131d19f049fec1fd943afd89855185d39
|
|
@ -80,9 +80,6 @@
|
|||||||
DA95D5F614DF0B9F008D1B94 /* IASKPSTextFieldSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CC14DF0691008D1B94 /* IASKPSTextFieldSpecifierViewCell.xib */; };
|
DA95D5F614DF0B9F008D1B94 /* IASKPSTextFieldSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CC14DF0691008D1B94 /* IASKPSTextFieldSpecifierViewCell.xib */; };
|
||||||
DA95D5F714DF0B9F008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CD14DF0691008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib */; };
|
DA95D5F714DF0B9F008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CD14DF0691008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib */; };
|
||||||
DA95D5F814DF0B9F008D1B94 /* IASKSpecifierValuesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CE14DF0691008D1B94 /* IASKSpecifierValuesView.xib */; };
|
DA95D5F814DF0B9F008D1B94 /* IASKSpecifierValuesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CE14DF0691008D1B94 /* IASKSpecifierValuesView.xib */; };
|
||||||
DAAC35DB156BD62F00C5FD93 /* libApptentiveConnect.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAAC35D2156BD51600C5FD93 /* libApptentiveConnect.a */; };
|
|
||||||
DAAC35DE156BD77D00C5FD93 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAAC35DD156BD77D00C5FD93 /* CoreTelephony.framework */; };
|
|
||||||
DAAC35E4156BDBA700C5FD93 /* Apptentive.plist in Resources */ = {isa = PBXBuildFile; fileRef = DAAC35E2156BDBA700C5FD93 /* Apptentive.plist */; };
|
|
||||||
DAB8D45D15036BCF00CED3BC /* MasterPassword.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D43C15036BCF00CED3BC /* MasterPassword.xcdatamodeld */; };
|
DAB8D45D15036BCF00CED3BC /* MasterPassword.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D43C15036BCF00CED3BC /* MasterPassword.xcdatamodeld */; };
|
||||||
DAB8D45E15036BCF00CED3BC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D43F15036BCF00CED3BC /* InfoPlist.strings */; };
|
DAB8D45E15036BCF00CED3BC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D43F15036BCF00CED3BC /* InfoPlist.strings */; };
|
||||||
DAB8D45F15036BCF00CED3BC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D44115036BCF00CED3BC /* main.m */; };
|
DAB8D45F15036BCF00CED3BC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D44115036BCF00CED3BC /* main.m */; };
|
||||||
@ -676,7 +673,6 @@
|
|||||||
DAC632891486D9690075AEA5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC632871486D95D0075AEA5 /* Security.framework */; };
|
DAC632891486D9690075AEA5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC632871486D95D0075AEA5 /* Security.framework */; };
|
||||||
DAC728CA157C247B00889EF2 /* MPPreferencesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC728C9157C247B00889EF2 /* MPPreferencesViewController.m */; };
|
DAC728CA157C247B00889EF2 /* MPPreferencesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC728C9157C247B00889EF2 /* MPPreferencesViewController.m */; };
|
||||||
DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||||
DACABB8515729E80008BA211 /* ApptentiveResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DAAC35D6156BD51600C5FD93 /* ApptentiveResources.bundle */; };
|
|
||||||
DACABB861572A2A7008BA211 /* tip_alert_black.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6BA15036BF600CED3BC /* tip_alert_black.png */; };
|
DACABB861572A2A7008BA211 /* tip_alert_black.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6BA15036BF600CED3BC /* tip_alert_black.png */; };
|
||||||
DACABB871572A2A7008BA211 /* tip_alert_black@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6BB15036BF600CED3BC /* tip_alert_black@2x.png */; };
|
DACABB871572A2A7008BA211 /* tip_alert_black@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6BB15036BF600CED3BC /* tip_alert_black@2x.png */; };
|
||||||
DACABB881572A2A7008BA211 /* tip_basic_black.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6CC15036BF600CED3BC /* tip_basic_black.png */; };
|
DACABB881572A2A7008BA211 /* tip_basic_black.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6CC15036BF600CED3BC /* tip_basic_black.png */; };
|
||||||
@ -824,6 +820,8 @@
|
|||||||
DAFE4A63150399FF003ABA8C /* UIControl+PearlSelect.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA8B /* UIControl+PearlSelect.h */; };
|
DAFE4A63150399FF003ABA8C /* UIControl+PearlSelect.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA8B /* UIControl+PearlSelect.h */; };
|
||||||
DAFE4A63150399FF003ABA8E /* UIScrollView+PearlFlashingIndicators.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA8D /* UIScrollView+PearlFlashingIndicators.m */; };
|
DAFE4A63150399FF003ABA8E /* UIScrollView+PearlFlashingIndicators.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA8D /* UIScrollView+PearlFlashingIndicators.m */; };
|
||||||
DAFE4A63150399FF003ABA90 /* UIScrollView+PearlFlashingIndicators.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA8F /* UIScrollView+PearlFlashingIndicators.h */; };
|
DAFE4A63150399FF003ABA90 /* UIScrollView+PearlFlashingIndicators.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA8F /* UIScrollView+PearlFlashingIndicators.h */; };
|
||||||
|
DAFE4A63150399FF003ABA92 /* NSDateFormatter+RFC3339.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA91 /* NSDateFormatter+RFC3339.m */; };
|
||||||
|
DAFE4A63150399FF003ABA94 /* NSDateFormatter+RFC3339.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA93 /* NSDateFormatter+RFC3339.h */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -855,41 +853,6 @@
|
|||||||
remoteGlobalIDString = DA67FE5D14E4834300DB7CC9;
|
remoteGlobalIDString = DA67FE5D14E4834300DB7CC9;
|
||||||
remoteInfo = util;
|
remoteInfo = util;
|
||||||
};
|
};
|
||||||
DAAC35D1156BD51600C5FD93 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */;
|
|
||||||
proxyType = 2;
|
|
||||||
remoteGlobalIDString = 496DC37F1333D35600743F65;
|
|
||||||
remoteInfo = ApptentiveConnect;
|
|
||||||
};
|
|
||||||
DAAC35D3156BD51600C5FD93 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */;
|
|
||||||
proxyType = 2;
|
|
||||||
remoteGlobalIDString = 496DC38C1333D35600743F65;
|
|
||||||
remoteInfo = ApptentiveConnectTests;
|
|
||||||
};
|
|
||||||
DAAC35D5156BD51600C5FD93 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */;
|
|
||||||
proxyType = 2;
|
|
||||||
remoteGlobalIDString = 49D1118C13341A7C00603373;
|
|
||||||
remoteInfo = ApptentiveResources;
|
|
||||||
};
|
|
||||||
DAAC35D7156BD61D00C5FD93 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = 496DC37E1333D35600743F65;
|
|
||||||
remoteInfo = ApptentiveConnect;
|
|
||||||
};
|
|
||||||
DAAC35D9156BD61D00C5FD93 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = 49D1118B13341A7C00603373;
|
|
||||||
remoteInfo = ApptentiveResources;
|
|
||||||
};
|
|
||||||
DAC63283148681200075AEA5 /* PBXContainerItemProxy */ = {
|
DAC63283148681200075AEA5 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||||
@ -993,11 +956,7 @@
|
|||||||
DA95D5CD14DF0691008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = IASKPSToggleSwitchSpecifierViewCell.xib; sourceTree = "<group>"; };
|
DA95D5CD14DF0691008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = IASKPSToggleSwitchSpecifierViewCell.xib; sourceTree = "<group>"; };
|
||||||
DA95D5CE14DF0691008D1B94 /* IASKSpecifierValuesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = IASKSpecifierValuesView.xib; sourceTree = "<group>"; };
|
DA95D5CE14DF0691008D1B94 /* IASKSpecifierValuesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = IASKSpecifierValuesView.xib; sourceTree = "<group>"; };
|
||||||
DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
|
DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
|
||||||
DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ApptentiveConnect.xcodeproj; path = External/apptentive/ApptentiveConnect/ApptentiveConnect.xcodeproj; sourceTree = "<group>"; };
|
|
||||||
DAAC35DD156BD77D00C5FD93 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
|
DAAC35DD156BD77D00C5FD93 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
|
||||||
DAAC35E2156BDBA700C5FD93 /* Apptentive.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Apptentive.plist; sourceTree = "<group>"; };
|
|
||||||
DAAC35E5156BDBC100C5FD93 /* ATConnect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ATConnect.h; path = ../External/apptentive/ApptentiveConnect/source/ATConnect.h; sourceTree = "<group>"; };
|
|
||||||
DAAC35E6156BDF0E00C5FD93 /* ATAppRatingFlow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ATAppRatingFlow.h; path = "../External/apptentive/ApptentiveConnect/source/Rating Flow/ATAppRatingFlow.h"; sourceTree = "<group>"; };
|
|
||||||
DAB8D43D15036BCF00CED3BC /* MasterPassword.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MasterPassword.xcdatamodel; sourceTree = "<group>"; };
|
DAB8D43D15036BCF00CED3BC /* MasterPassword.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MasterPassword.xcdatamodel; sourceTree = "<group>"; };
|
||||||
DAB8D44015036BCF00CED3BC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
DAB8D44015036BCF00CED3BC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
DAB8D44115036BCF00CED3BC /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
DAB8D44115036BCF00CED3BC /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
@ -1817,6 +1776,8 @@
|
|||||||
DAFE4A63150399FF003ABA8B /* UIControl+PearlSelect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+PearlSelect.h"; sourceTree = "<group>"; };
|
DAFE4A63150399FF003ABA8B /* UIControl+PearlSelect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+PearlSelect.h"; sourceTree = "<group>"; };
|
||||||
DAFE4A63150399FF003ABA8D /* UIScrollView+PearlFlashingIndicators.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlFlashingIndicators.m"; sourceTree = "<group>"; };
|
DAFE4A63150399FF003ABA8D /* UIScrollView+PearlFlashingIndicators.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlFlashingIndicators.m"; sourceTree = "<group>"; };
|
||||||
DAFE4A63150399FF003ABA8F /* UIScrollView+PearlFlashingIndicators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlFlashingIndicators.h"; sourceTree = "<group>"; };
|
DAFE4A63150399FF003ABA8F /* UIScrollView+PearlFlashingIndicators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlFlashingIndicators.h"; sourceTree = "<group>"; };
|
||||||
|
DAFE4A63150399FF003ABA91 /* NSDateFormatter+RFC3339.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDateFormatter+RFC3339.m"; sourceTree = "<group>"; };
|
||||||
|
DAFE4A63150399FF003ABA93 /* NSDateFormatter+RFC3339.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDateFormatter+RFC3339.h"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -1832,8 +1793,6 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
DAAC35DE156BD77D00C5FD93 /* CoreTelephony.framework in Frameworks */,
|
|
||||||
DAAC35DB156BD62F00C5FD93 /* libApptentiveConnect.a in Frameworks */,
|
|
||||||
DA44260A1557D9E40052177D /* libiCloudStoreManager.a in Frameworks */,
|
DA44260A1557D9E40052177D /* libiCloudStoreManager.a in Frameworks */,
|
||||||
DAD312C21552A22700A3F9ED /* libsqlite3.dylib in Frameworks */,
|
DAD312C21552A22700A3F9ED /* libsqlite3.dylib in Frameworks */,
|
||||||
DAD312BF1552A1BD00A3F9ED /* libLocalytics.a in Frameworks */,
|
DAD312BF1552A1BD00A3F9ED /* libLocalytics.a in Frameworks */,
|
||||||
@ -1913,7 +1872,6 @@
|
|||||||
DA5BFA39147E415C00F98B1E = {
|
DA5BFA39147E415C00F98B1E = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */,
|
|
||||||
DA79A9BD1557DDC700BAA07A /* scrypt.xcodeproj */,
|
DA79A9BD1557DDC700BAA07A /* scrypt.xcodeproj */,
|
||||||
DA5BFA50147E415C00F98B1E /* MasterPassword */,
|
DA5BFA50147E415C00F98B1E /* MasterPassword */,
|
||||||
DAB8D46F15036BF600CED3BC /* Resources */,
|
DAB8D46F15036BF600CED3BC /* Resources */,
|
||||||
@ -1925,7 +1883,6 @@
|
|||||||
DAD3125E15528C9C00A3F9ED /* Crashlytics */,
|
DAD3125E15528C9C00A3F9ED /* Crashlytics */,
|
||||||
DAD3126115528C9C00A3F9ED /* TestFlight */,
|
DAD3126115528C9C00A3F9ED /* TestFlight */,
|
||||||
DAD3127315528CD200A3F9ED /* Localytics */,
|
DAD3127315528CD200A3F9ED /* Localytics */,
|
||||||
DAAC35E0156BDBA700C5FD93 /* Apptentive */,
|
|
||||||
DA4425D71557BF260052177D /* iCloudStoreManager */,
|
DA4425D71557BF260052177D /* iCloudStoreManager */,
|
||||||
DA5BFA47147E415C00F98B1E /* Frameworks */,
|
DA5BFA47147E415C00F98B1E /* Frameworks */,
|
||||||
DA5BFA45147E415C00F98B1E /* Products */,
|
DA5BFA45147E415C00F98B1E /* Products */,
|
||||||
@ -2128,26 +2085,6 @@
|
|||||||
path = External/InAppSettingsKit/InAppSettingsKit/Xibs;
|
path = External/InAppSettingsKit/InAppSettingsKit/Xibs;
|
||||||
sourceTree = SOURCE_ROOT;
|
sourceTree = SOURCE_ROOT;
|
||||||
};
|
};
|
||||||
DAAC35C9156BD51500C5FD93 /* Products */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
DAAC35D2156BD51600C5FD93 /* libApptentiveConnect.a */,
|
|
||||||
DAAC35D4156BD51600C5FD93 /* ApptentiveConnectTests.octest */,
|
|
||||||
DAAC35D6156BD51600C5FD93 /* ApptentiveResources.bundle */,
|
|
||||||
);
|
|
||||||
name = Products;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
DAAC35E0156BDBA700C5FD93 /* Apptentive */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
DAAC35E6156BDF0E00C5FD93 /* ATAppRatingFlow.h */,
|
|
||||||
DAAC35E5156BDBC100C5FD93 /* ATConnect.h */,
|
|
||||||
DAAC35E2156BDBA700C5FD93 /* Apptentive.plist */,
|
|
||||||
);
|
|
||||||
path = Apptentive;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
DAB8D43E15036BCF00CED3BC /* iOS */ = {
|
DAB8D43E15036BCF00CED3BC /* iOS */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -3006,6 +2943,8 @@
|
|||||||
DAFE45D715039823003ABA7C /* Pearl */ = {
|
DAFE45D715039823003ABA7C /* Pearl */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DAFE4A63150399FF003ABA93 /* NSDateFormatter+RFC3339.h */,
|
||||||
|
DAFE4A63150399FF003ABA91 /* NSDateFormatter+RFC3339.m */,
|
||||||
DAFE4A63150399FF003ABA87 /* NSObject+PearlKVO.h */,
|
DAFE4A63150399FF003ABA87 /* NSObject+PearlKVO.h */,
|
||||||
DAFE4A63150399FF003ABA85 /* NSObject+PearlKVO.m */,
|
DAFE4A63150399FF003ABA85 /* NSObject+PearlKVO.m */,
|
||||||
DA30E9CB15722ECA00A68B4C /* NSBundle+PearlMutableInfo.h */,
|
DA30E9CB15722ECA00A68B4C /* NSBundle+PearlMutableInfo.h */,
|
||||||
@ -3229,6 +3168,7 @@
|
|||||||
DAFE4A63150399FF003ABA88 /* NSObject+PearlKVO.h in Headers */,
|
DAFE4A63150399FF003ABA88 /* NSObject+PearlKVO.h in Headers */,
|
||||||
DAFE4A63150399FF003ABA8C /* UIControl+PearlSelect.h in Headers */,
|
DAFE4A63150399FF003ABA8C /* UIControl+PearlSelect.h in Headers */,
|
||||||
DAFE4A63150399FF003ABA90 /* UIScrollView+PearlFlashingIndicators.h in Headers */,
|
DAFE4A63150399FF003ABA90 /* UIScrollView+PearlFlashingIndicators.h in Headers */,
|
||||||
|
DAFE4A63150399FF003ABA94 /* NSDateFormatter+RFC3339.h in Headers */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -3277,8 +3217,6 @@
|
|||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
DAAC35D8156BD61D00C5FD93 /* PBXTargetDependency */,
|
|
||||||
DAAC35DA156BD61D00C5FD93 /* PBXTargetDependency */,
|
|
||||||
);
|
);
|
||||||
name = MasterPassword;
|
name = MasterPassword;
|
||||||
productName = MasterPassword;
|
productName = MasterPassword;
|
||||||
@ -3395,10 +3333,6 @@
|
|||||||
productRefGroup = DA5BFA45147E415C00F98B1E /* Products */;
|
productRefGroup = DA5BFA45147E415C00F98B1E /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectReferences = (
|
projectReferences = (
|
||||||
{
|
|
||||||
ProductGroup = DAAC35C9156BD51500C5FD93 /* Products */;
|
|
||||||
ProjectRef = DAAC35C8156BD51500C5FD93 /* ApptentiveConnect.xcodeproj */;
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
ProductGroup = DA79A9BE1557DDC700BAA07A /* Products */;
|
ProductGroup = DA79A9BE1557DDC700BAA07A /* Products */;
|
||||||
ProjectRef = DA79A9BD1557DDC700BAA07A /* scrypt.xcodeproj */;
|
ProjectRef = DA79A9BD1557DDC700BAA07A /* scrypt.xcodeproj */;
|
||||||
@ -3439,27 +3373,6 @@
|
|||||||
remoteRef = DA79A9D11557DDC800BAA07A /* PBXContainerItemProxy */;
|
remoteRef = DA79A9D11557DDC800BAA07A /* PBXContainerItemProxy */;
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
};
|
};
|
||||||
DAAC35D2156BD51600C5FD93 /* libApptentiveConnect.a */ = {
|
|
||||||
isa = PBXReferenceProxy;
|
|
||||||
fileType = archive.ar;
|
|
||||||
path = libApptentiveConnect.a;
|
|
||||||
remoteRef = DAAC35D1156BD51600C5FD93 /* PBXContainerItemProxy */;
|
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
|
||||||
};
|
|
||||||
DAAC35D4156BD51600C5FD93 /* ApptentiveConnectTests.octest */ = {
|
|
||||||
isa = PBXReferenceProxy;
|
|
||||||
fileType = wrapper.cfbundle;
|
|
||||||
path = ApptentiveConnectTests.octest;
|
|
||||||
remoteRef = DAAC35D3156BD51600C5FD93 /* PBXContainerItemProxy */;
|
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
|
||||||
};
|
|
||||||
DAAC35D6156BD51600C5FD93 /* ApptentiveResources.bundle */ = {
|
|
||||||
isa = PBXReferenceProxy;
|
|
||||||
fileType = wrapper.cfbundle;
|
|
||||||
path = ApptentiveResources.bundle;
|
|
||||||
remoteRef = DAAC35D5156BD51600C5FD93 /* PBXContainerItemProxy */;
|
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
|
||||||
};
|
|
||||||
/* End PBXReferenceProxy section */
|
/* End PBXReferenceProxy section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
@ -4056,8 +3969,6 @@
|
|||||||
DA0A1D0615690A9A0092735D /* Default@2x.png in Resources */,
|
DA0A1D0615690A9A0092735D /* Default@2x.png in Resources */,
|
||||||
DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */,
|
DA0A1D1515690AF40092735D /* Icon-72@2x.png in Resources */,
|
||||||
DA0A1D1615690AF40092735D /* Icon-Small-50@2x.png in Resources */,
|
DA0A1D1615690AF40092735D /* Icon-Small-50@2x.png in Resources */,
|
||||||
DAAC35E4156BDBA700C5FD93 /* Apptentive.plist in Resources */,
|
|
||||||
DACABB8515729E80008BA211 /* ApptentiveResources.bundle in Resources */,
|
|
||||||
DACABB861572A2A7008BA211 /* tip_alert_black.png in Resources */,
|
DACABB861572A2A7008BA211 /* tip_alert_black.png in Resources */,
|
||||||
DACABB871572A2A7008BA211 /* tip_alert_black@2x.png in Resources */,
|
DACABB871572A2A7008BA211 /* tip_alert_black@2x.png in Resources */,
|
||||||
DACABB881572A2A7008BA211 /* tip_basic_black.png in Resources */,
|
DACABB881572A2A7008BA211 /* tip_basic_black.png in Resources */,
|
||||||
@ -4263,6 +4174,7 @@
|
|||||||
DAFE4A63150399FF003ABA86 /* NSObject+PearlKVO.m in Sources */,
|
DAFE4A63150399FF003ABA86 /* NSObject+PearlKVO.m in Sources */,
|
||||||
DAFE4A63150399FF003ABA8A /* UIControl+PearlSelect.m in Sources */,
|
DAFE4A63150399FF003ABA8A /* UIControl+PearlSelect.m in Sources */,
|
||||||
DAFE4A63150399FF003ABA8E /* UIScrollView+PearlFlashingIndicators.m in Sources */,
|
DAFE4A63150399FF003ABA8E /* UIScrollView+PearlFlashingIndicators.m in Sources */,
|
||||||
|
DAFE4A63150399FF003ABA92 /* NSDateFormatter+RFC3339.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -4285,16 +4197,6 @@
|
|||||||
name = "Makefile-scrypt";
|
name = "Makefile-scrypt";
|
||||||
targetProxy = DA4DA1D71564470200F6F596 /* PBXContainerItemProxy */;
|
targetProxy = DA4DA1D71564470200F6F596 /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
DAAC35D8156BD61D00C5FD93 /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
name = ApptentiveConnect;
|
|
||||||
targetProxy = DAAC35D7156BD61D00C5FD93 /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
DAAC35DA156BD61D00C5FD93 /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
name = ApptentiveResources;
|
|
||||||
targetProxy = DAAC35D9156BD61D00C5FD93 /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
DAC63284148681200075AEA5 /* PBXTargetDependency */ = {
|
DAC63284148681200075AEA5 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = DAC6325C1486805C0075AEA5 /* uicolor-utilities */;
|
target = DAC6325C1486805C0075AEA5 /* uicolor-utilities */;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#import <Crashlytics/Crashlytics.h>
|
#import <Crashlytics/Crashlytics.h>
|
||||||
#import "MPAppDelegate_Key.h"
|
#import "MPAppDelegate_Key.h"
|
||||||
#import "MPAppDelegate_Store.h"
|
#import "MPAppDelegate_Store.h"
|
||||||
#import "ATConnect.h"
|
|
||||||
#import "LocalyticsSession.h"
|
#import "LocalyticsSession.h"
|
||||||
|
|
||||||
@implementation MPAppDelegate_Shared (Key)
|
@implementation MPAppDelegate_Shared (Key)
|
||||||
@ -28,11 +27,11 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
|
|
||||||
NSData *key = [PearlKeyChain dataOfItemForQuery:keyQuery(user)];
|
NSData *key = [PearlKeyChain dataOfItemForQuery:keyQuery(user)];
|
||||||
if (key)
|
if (key)
|
||||||
inf(@"Found key (for: %@) in keychain.", user.name);
|
inf(@"Found key in keychain for: %@", user.userID);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
user.saveKey = NO;
|
user.saveKey = NO;
|
||||||
inf(@"No key found (for: %@) in keychain.", user.name);
|
inf(@"No key found in keychain for: %@", user.userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
@ -44,7 +43,8 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
NSData *existingKey = [PearlKeyChain dataOfItemForQuery:keyQuery(user)];
|
NSData *existingKey = [PearlKeyChain dataOfItemForQuery:keyQuery(user)];
|
||||||
|
|
||||||
if (![existingKey isEqualToData:self.key]) {
|
if (![existingKey isEqualToData:self.key]) {
|
||||||
inf(@"Updating key in keychain.");
|
inf(@"Saving key in keychain for: %@", user.userID);
|
||||||
|
|
||||||
[PearlKeyChain addOrUpdateItemForQuery:keyQuery(user)
|
[PearlKeyChain addOrUpdateItemForQuery:keyQuery(user)
|
||||||
withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
self.key, (__bridge id)kSecValueData,
|
self.key, (__bridge id)kSecValueData,
|
||||||
@ -63,7 +63,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
user.saveKey = NO;
|
user.saveKey = NO;
|
||||||
|
|
||||||
if (result == noErr) {
|
if (result == noErr) {
|
||||||
inf(@"Removed key (for: %@) from keychain.", user.name);
|
inf(@"Removed key from keychain for: %@", user.userID);
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPNotificationKeyForgotten object:self];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPNotificationKeyForgotten object:self];
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
@ -105,14 +105,10 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
if ((tryKey = [self loadSavedKeyFor:user]))
|
if ((tryKey = [self loadSavedKeyFor:user]))
|
||||||
if (![user.keyID isEqual:keyIDForKey(tryKey)]) {
|
if (![user.keyID isEqual:keyIDForKey(tryKey)]) {
|
||||||
// Loaded password doesn't match user's keyID. Forget saved password: it is incorrect.
|
// Loaded password doesn't match user's keyID. Forget saved password: it is incorrect.
|
||||||
|
inf(@"Saved password doesn't match keyID for: %@", user.userID);
|
||||||
|
|
||||||
tryKey = nil;
|
tryKey = nil;
|
||||||
[self forgetSavedKeyFor:user];
|
[self forgetSavedKeyFor:user];
|
||||||
|
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointSignInFailed];
|
|
||||||
#endif
|
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointSignInFailed
|
|
||||||
attributes:nil];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,19 +117,24 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
if ([password length])
|
if ([password length])
|
||||||
if ((tryKey = keyForPassword(password, user.name)))
|
if ((tryKey = keyForPassword(password, user.name)))
|
||||||
if (![user.keyID isEqual:keyIDForKey(tryKey)]) {
|
if (![user.keyID isEqual:keyIDForKey(tryKey)]) {
|
||||||
tryKey = nil;
|
inf(@"Key derived from password doesn't match keyID for: %@", user.userID);
|
||||||
|
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
tryKey = nil;
|
||||||
[TestFlight passCheckpoint:MPCheckpointSignInFailed];
|
|
||||||
#endif
|
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointSignInFailed
|
|
||||||
attributes:nil];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No more methods left, fail if key still not known.
|
// No more methods left, fail if key still not known.
|
||||||
if (!tryKey)
|
if (!tryKey) {
|
||||||
|
inf(@"Login failed for: %@", user.userID);
|
||||||
|
|
||||||
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
|
[TestFlight passCheckpoint:MPCheckpointSignInFailed];
|
||||||
|
#endif
|
||||||
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointSignInFailed attributes:nil];
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
|
}
|
||||||
|
inf(@"Logged in: %@", user.userID);
|
||||||
|
|
||||||
if (![self.key isEqualToData:tryKey]) {
|
if (![self.key isEqualToData:tryKey]) {
|
||||||
self.key = tryKey;
|
self.key = tryKey;
|
||||||
@ -141,10 +142,9 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@try {
|
@try {
|
||||||
if ([[MPiOSConfig get].sendDebugInfo boolValue]) {
|
if ([[MPiOSConfig get].sendInfo boolValue]) {
|
||||||
[TestFlight addCustomEnvironmentInformation:user.name forKey:@"username"];
|
[TestFlight addCustomEnvironmentInformation:user.userID forKey:@"username"];
|
||||||
[[Crashlytics sharedInstance] setObjectValue:user.name forKey:@"username"];
|
[[Crashlytics sharedInstance] setObjectValue:user.userID forKey:@"username"];
|
||||||
[[ATConnect sharedConnection] addAdditionalInfoToFeedback:user.name withKey:@"username"];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@catch (id exception) {
|
@catch (id exception) {
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
@implementation MPAppDelegate_Shared (Store)
|
@implementation MPAppDelegate_Shared (Store)
|
||||||
|
|
||||||
static NSDateFormatter *rfc3339DateFormatter = nil;
|
|
||||||
|
|
||||||
#pragma mark - Core Data setup
|
#pragma mark - Core Data setup
|
||||||
|
|
||||||
+ (NSManagedObjectContext *)managedObjectContext {
|
+ (NSManagedObjectContext *)managedObjectContext {
|
||||||
@ -136,26 +134,27 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
|
|
||||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didSwitchToiCloud:(BOOL)iCloudEnabled {
|
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didSwitchToiCloud:(BOOL)iCloudEnabled {
|
||||||
|
|
||||||
// manager.iCloudEnabled is more reliable (eg. iOS tampers with didSwitch a bit)
|
// manager.iCloudEnabled is more reliable (eg. iOS' MPAppDelegate tampers with didSwitch a bit)
|
||||||
iCloudEnabled = manager.iCloudEnabled;
|
iCloudEnabled = manager.iCloudEnabled;
|
||||||
|
inf(@"Using iCloud? %@", iCloudEnabled? @"YES": @"NO");
|
||||||
|
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
[TestFlight passCheckpoint:iCloudEnabled? MPCheckpointCloudEnabled: MPCheckpointCloudDisabled];
|
[TestFlight passCheckpoint:iCloudEnabled? MPCheckpointCloudEnabled: MPCheckpointCloudDisabled];
|
||||||
#endif
|
#endif
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:iCloudEnabled? MPCheckpointCloudEnabled: MPCheckpointCloudDisabled
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointCloud
|
||||||
attributes:nil];
|
attributes:[NSDictionary dictionaryWithObject:iCloudEnabled? @"YES": @"NO" forKey:@"enabled"]];
|
||||||
|
|
||||||
inf(@"Using iCloud? %@", iCloudEnabled? @"YES": @"NO");
|
|
||||||
[MPConfig get].iCloud = [NSNumber numberWithBool:iCloudEnabled];
|
[MPConfig get].iCloud = [NSNumber numberWithBool:iCloudEnabled];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didEncounterError:(NSError *)error cause:(UbiquityStoreManagerErrorCause)cause
|
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didEncounterError:(NSError *)error cause:(UbiquityStoreManagerErrorCause)cause
|
||||||
context:(id)context {
|
context:(id)context {
|
||||||
|
|
||||||
|
err(@"StoreManager: cause=%d, context=%@, error=%@", cause, context, error);
|
||||||
|
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
[TestFlight passCheckpoint:PearlString(@"MPCheckpointMPErrorUbiquity_%d", cause)];
|
[TestFlight passCheckpoint:PearlString(@"MPCheckpointMPErrorUbiquity_%d", cause)];
|
||||||
#endif
|
#endif
|
||||||
err(@"StoreManager: cause=%d, context=%@, error=%@", cause, context, error);
|
|
||||||
|
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case UbiquityStoreManagerErrorCauseDeleteStore:
|
case UbiquityStoreManagerErrorCauseDeleteStore:
|
||||||
@ -164,12 +163,13 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
case UbiquityStoreManagerErrorCauseClearStore:
|
case UbiquityStoreManagerErrorCauseClearStore:
|
||||||
break;
|
break;
|
||||||
case UbiquityStoreManagerErrorCauseOpenLocalStore: {
|
case UbiquityStoreManagerErrorCauseOpenLocalStore: {
|
||||||
|
wrn(@"Local store could not be opened, resetting it.");
|
||||||
|
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
[TestFlight passCheckpoint:MPCheckpointLocalStoreIncompatible];
|
[TestFlight passCheckpoint:MPCheckpointLocalStoreIncompatible];
|
||||||
#endif
|
#endif
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointLocalStoreIncompatible
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointLocalStoreIncompatible
|
||||||
attributes:nil];
|
attributes:nil];
|
||||||
wrn(@"Local store could not be opened, resetting it.");
|
|
||||||
manager.hardResetEnabled = YES;
|
manager.hardResetEnabled = YES;
|
||||||
[manager hardResetLocalStorage];
|
[manager hardResetLocalStorage];
|
||||||
|
|
||||||
@ -177,12 +177,13 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case UbiquityStoreManagerErrorCauseOpenCloudStore: {
|
case UbiquityStoreManagerErrorCauseOpenCloudStore: {
|
||||||
|
wrn(@"iCloud store could not be opened, resetting it.");
|
||||||
|
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
[TestFlight passCheckpoint:MPCheckpointCloudStoreIncompatible];
|
[TestFlight passCheckpoint:MPCheckpointCloudStoreIncompatible];
|
||||||
#endif
|
#endif
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointCloudStoreIncompatible
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointCloudStoreIncompatible
|
||||||
attributes:nil];
|
attributes:nil];
|
||||||
wrn(@"iCloud store could not be opened, resetting it.");
|
|
||||||
manager.hardResetEnabled = YES;
|
manager.hardResetEnabled = YES;
|
||||||
[manager hardResetCloudStorage];
|
[manager hardResetCloudStorage];
|
||||||
break;
|
break;
|
||||||
@ -192,22 +193,10 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
|
|
||||||
#pragma mark - Import / Export
|
#pragma mark - Import / Export
|
||||||
|
|
||||||
- (void)loadRFC3339DateFormatter {
|
|
||||||
|
|
||||||
if (rfc3339DateFormatter)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rfc3339DateFormatter = [NSDateFormatter new];
|
|
||||||
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
|
|
||||||
[rfc3339DateFormatter setLocale:enUSPOSIXLocale];
|
|
||||||
[rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
|
|
||||||
[rfc3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (MPImportResult)importSites:(NSString *)importedSitesString withPassword:(NSString *)password
|
- (MPImportResult)importSites:(NSString *)importedSitesString withPassword:(NSString *)password
|
||||||
askConfirmation:(BOOL(^)(NSUInteger importCount, NSUInteger deleteCount))confirmation {
|
askConfirmation:(BOOL(^)(NSUInteger importCount, NSUInteger deleteCount))confirmation {
|
||||||
|
|
||||||
[self loadRFC3339DateFormatter];
|
inf(@"Importing sites.");
|
||||||
|
|
||||||
static NSRegularExpression *headerPattern, *sitePattern;
|
static NSRegularExpression *headerPattern, *sitePattern;
|
||||||
__autoreleasing NSError *error;
|
__autoreleasing NSError *error;
|
||||||
@ -299,17 +288,24 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
NSArray *existingSites = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
|
NSArray *existingSites = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
|
||||||
if (error)
|
if (error)
|
||||||
err(@"Couldn't search existing sites: %@", error);
|
err(@"Couldn't search existing sites: %@", error);
|
||||||
if (!existingSites)
|
if (!existingSites) {
|
||||||
|
err(@"Lookup of existing sites failed for site: %@, user: %@", name, user.userID);
|
||||||
return MPImportResultInternalError;
|
return MPImportResultInternalError;
|
||||||
|
}
|
||||||
|
|
||||||
[elementsToDelete addObjectsFromArray:existingSites];
|
[elementsToDelete addObjectsFromArray:existingSites];
|
||||||
[importedSiteElements addObject:[NSArray arrayWithObjects:lastUsed, uses, type, name, exportContent, nil]];
|
[importedSiteElements addObject:[NSArray arrayWithObjects:lastUsed, uses, type, name, exportContent, nil]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inf(@"Importing %u sites, deleting %u sites, for user: %@",
|
||||||
|
[importedSiteElements count], [elementsToDelete count], [MPUserEntity idFor:userName]);
|
||||||
|
|
||||||
// Ask for confirmation to import these sites.
|
// Ask for confirmation to import these sites.
|
||||||
if (!confirmation([importedSiteElements count], [elementsToDelete count]))
|
if (!confirmation([importedSiteElements count], [elementsToDelete count])) {
|
||||||
|
inf(@"Import cancelled.");
|
||||||
return MPImportResultCancelled;
|
return MPImportResultCancelled;
|
||||||
|
}
|
||||||
|
|
||||||
// Delete existing sites.
|
// Delete existing sites.
|
||||||
[elementsToDelete enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
|
[elementsToDelete enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
|
||||||
@ -326,7 +322,7 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
user.keyID = [keyIDHex decodeHex];
|
user.keyID = [keyIDHex decodeHex];
|
||||||
}
|
}
|
||||||
for (NSArray *siteElements in importedSiteElements) {
|
for (NSArray *siteElements in importedSiteElements) {
|
||||||
NSDate *lastUsed = [rfc3339DateFormatter dateFromString:[siteElements objectAtIndex:0]];
|
NSDate *lastUsed = [[NSDateFormatter rfc3339DateFormatter] dateFromString:[siteElements objectAtIndex:0]];
|
||||||
NSUInteger uses = (unsigned)[[siteElements objectAtIndex:1] integerValue];
|
NSUInteger uses = (unsigned)[[siteElements objectAtIndex:1] integerValue];
|
||||||
MPElementType type = (MPElementType)[[siteElements objectAtIndex:2] integerValue];
|
MPElementType type = (MPElementType)[[siteElements objectAtIndex:2] integerValue];
|
||||||
NSString *name = [siteElements objectAtIndex:3];
|
NSString *name = [siteElements objectAtIndex:3];
|
||||||
@ -345,6 +341,7 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
}
|
}
|
||||||
[self saveContext];
|
[self saveContext];
|
||||||
|
|
||||||
|
inf(@"Import completed successfully.");
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
[TestFlight passCheckpoint:MPCheckpointSitesImported];
|
[TestFlight passCheckpoint:MPCheckpointSitesImported];
|
||||||
#endif
|
#endif
|
||||||
@ -356,7 +353,7 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
|
|
||||||
- (NSString *)exportSitesShowingPasswords:(BOOL)showPasswords {
|
- (NSString *)exportSitesShowingPasswords:(BOOL)showPasswords {
|
||||||
|
|
||||||
[self loadRFC3339DateFormatter];
|
inf(@"Exporting sites, %@, for: %@", showPasswords? @"showing passwords": @"omitting passwords", self.activeUser.userID);
|
||||||
|
|
||||||
// Header.
|
// Header.
|
||||||
NSMutableString *export = [NSMutableString new];
|
NSMutableString *export = [NSMutableString new];
|
||||||
@ -370,7 +367,7 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
||||||
[export appendFormat:@"# User Name: %@\n", self.activeUser.name];
|
[export appendFormat:@"# User Name: %@\n", self.activeUser.name];
|
||||||
[export appendFormat:@"# Key ID: %@\n", [self.activeUser.keyID encodeHex]];
|
[export appendFormat:@"# Key ID: %@\n", [self.activeUser.keyID encodeHex]];
|
||||||
[export appendFormat:@"# Date: %@\n", [rfc3339DateFormatter stringFromDate:[NSDate date]]];
|
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
|
||||||
if (showPasswords)
|
if (showPasswords)
|
||||||
[export appendFormat:@"# Passwords: VISIBLE\n"];
|
[export appendFormat:@"# Passwords: VISIBLE\n"];
|
||||||
else
|
else
|
||||||
@ -398,15 +395,14 @@ static NSDateFormatter *rfc3339DateFormatter = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
[export appendFormat:@"%@ %8d %8d %20s\t%@\n",
|
[export appendFormat:@"%@ %8d %8d %20s\t%@\n",
|
||||||
[rfc3339DateFormatter stringFromDate:lastUsed], uses, type, [name cStringUsingEncoding:NSUTF8StringEncoding], content
|
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:lastUsed], uses, type, [name cStringUsingEncoding:NSUTF8StringEncoding], content
|
||||||
? content: @""];
|
? content: @""];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TESTFLIGHT_SDK_VERSION
|
#ifdef TESTFLIGHT_SDK_VERSION
|
||||||
[TestFlight passCheckpoint:MPCheckpointSitesExported];
|
[TestFlight passCheckpoint:MPCheckpointSitesExported];
|
||||||
#endif
|
#endif
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointSitesExported
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointSitesExported attributes:nil];
|
||||||
attributes:nil];
|
|
||||||
|
|
||||||
return export;
|
return export;
|
||||||
}
|
}
|
||||||
|
@ -36,5 +36,8 @@
|
|||||||
@property (assign) NSUInteger avatar;
|
@property (assign) NSUInteger avatar;
|
||||||
@property (assign) BOOL saveKey;
|
@property (assign) BOOL saveKey;
|
||||||
@property (assign) MPElementType defaultType;
|
@property (assign) MPElementType defaultType;
|
||||||
|
@property (readonly) NSString *userID;
|
||||||
|
|
||||||
|
+ (NSString *)idFor:(NSString *)userName;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -178,9 +178,20 @@
|
|||||||
return (MPElementType)[self.defaultType_ unsignedIntegerValue];
|
return (MPElementType)[self.defaultType_ unsignedIntegerValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)userID {
|
||||||
|
|
||||||
|
return [MPUserEntity idFor:self.name];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)setDefaultType:(MPElementType)aDefaultType {
|
- (void)setDefaultType:(MPElementType)aDefaultType {
|
||||||
|
|
||||||
self.defaultType_ = PearlUnsignedInteger(aDefaultType);
|
self.defaultType_ = PearlUnsignedInteger(aDefaultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSString *)idFor:(NSString *)userName {
|
||||||
|
|
||||||
|
return [[userName hashWith:PearlHashSHA1] encodeHex];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -64,6 +64,8 @@ typedef enum {
|
|||||||
#define MPCheckpointCloudStoreIncompatible @"MPCheckpointCloudStoreIncompatible"
|
#define MPCheckpointCloudStoreIncompatible @"MPCheckpointCloudStoreIncompatible"
|
||||||
#define MPCheckpointSignInFailed @"MPCheckpointSignInFailed"
|
#define MPCheckpointSignInFailed @"MPCheckpointSignInFailed"
|
||||||
#define MPCheckpointSignedIn @"MPCheckpointSignedIn"
|
#define MPCheckpointSignedIn @"MPCheckpointSignedIn"
|
||||||
|
#define MPCheckpointConfig @"MPCheckpointConfig"
|
||||||
|
#define MPCheckpointCloud @"MPCheckpointCloud"
|
||||||
#define MPCheckpointCloudEnabled @"MPCheckpointCloudEnabled"
|
#define MPCheckpointCloudEnabled @"MPCheckpointCloudEnabled"
|
||||||
#define MPCheckpointCloudDisabled @"MPCheckpointCloudDisabled"
|
#define MPCheckpointCloudDisabled @"MPCheckpointCloudDisabled"
|
||||||
#define MPCheckpointSitesImported @"MPCheckpointSitesImported"
|
#define MPCheckpointSitesImported @"MPCheckpointSitesImported"
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#import "IASKSettingsReader.h"
|
#import "IASKSettingsReader.h"
|
||||||
#import "LocalyticsSession.h"
|
#import "LocalyticsSession.h"
|
||||||
#import "ATConnect.h"
|
|
||||||
|
|
||||||
@interface MPAppDelegate ()
|
@interface MPAppDelegate ()
|
||||||
|
|
||||||
@ -23,9 +22,6 @@
|
|||||||
- (NSDictionary *)crashlyticsInfo;
|
- (NSDictionary *)crashlyticsInfo;
|
||||||
- (NSString *)crashlyticsAPIKey;
|
- (NSString *)crashlyticsAPIKey;
|
||||||
|
|
||||||
- (NSDictionary *)apptentiveInfo;
|
|
||||||
- (NSString *)apptentiveAPIKey;
|
|
||||||
|
|
||||||
- (NSDictionary *)localyticsInfo;
|
- (NSDictionary *)localyticsInfo;
|
||||||
- (NSString *)localyticsKey;
|
- (NSString *)localyticsKey;
|
||||||
|
|
||||||
@ -49,214 +45,85 @@
|
|||||||
return (MPAppDelegate *)[super get];
|
return (MPAppDelegate *)[super get];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)checkConfig {
|
|
||||||
|
|
||||||
if ([[MPConfig get].iCloud boolValue] != [self.storeManager iCloudEnabled])
|
|
||||||
[self.storeManager useiCloudStore:[[MPConfig get].iCloud boolValue] alertUser:YES];
|
|
||||||
if ([[MPiOSConfig get].sendDebugInfo boolValue]) {
|
|
||||||
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].rememberLogin boolValue] forKey:@"rememberLogin"];
|
|
||||||
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].iCloud boolValue] forKey:@"iCloud"];
|
|
||||||
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].iCloudDecided boolValue] forKey:@"iCloudDecided"];
|
|
||||||
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].sendDebugInfo boolValue] forKey:@"sendDebugInfo"];
|
|
||||||
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].helpHidden boolValue] forKey:@"helpHidden"];
|
|
||||||
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].showQuickStart 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"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)showGuide {
|
|
||||||
|
|
||||||
[self.navigationController performSegueWithIdentifier:@"MP_Guide" sender:self];
|
|
||||||
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointShowGuide];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)export {
|
|
||||||
|
|
||||||
[PearlAlert showNotice:
|
|
||||||
@"This will export all your site names.\n\n"
|
|
||||||
@"You can open the export with a text editor to get an overview of all your sites.\n\n"
|
|
||||||
@"The file also acts as a personal backup of your site list in case you don't sync with iCloud/iTunes."
|
|
||||||
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
|
||||||
[PearlAlert showAlertWithTitle:@"Reveal Passwords?" message:
|
|
||||||
@"Would you like to make all your passwords visible in the export?\n\n"
|
|
||||||
@"A safe export will only include your stored passwords, in an encrypted manner, "
|
|
||||||
@"making the result safe from falling in the wrong hands.\n\n"
|
|
||||||
@"If all your passwords are shown and somebody else finds the export, "
|
|
||||||
@"they could gain access to all your sites!"
|
|
||||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
|
||||||
tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
|
||||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 0)
|
|
||||||
// Safe Export
|
|
||||||
[self exportShowPasswords:NO];
|
|
||||||
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1)
|
|
||||||
// Safe Export
|
|
||||||
[self exportShowPasswords:YES];
|
|
||||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil];
|
|
||||||
} otherTitles:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)exportShowPasswords:(BOOL)showPasswords {
|
|
||||||
|
|
||||||
NSString *exportedSites = [self exportSitesShowingPasswords:showPasswords];
|
|
||||||
NSString *message;
|
|
||||||
if (showPasswords)
|
|
||||||
message = @"Export of my Master Password sites with passwords visible.\n\nREMINDER: Make sure nobody else sees this file!\n";
|
|
||||||
else
|
|
||||||
message = @"Backup of my Master Password sites.\n";
|
|
||||||
|
|
||||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
|
||||||
[exportDateFormatter setDateFormat:@"'Master Password sites ('yyyy'-'MM'-'DD').mpsites'"];
|
|
||||||
|
|
||||||
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
|
|
||||||
[composer setMailComposeDelegate:self];
|
|
||||||
[composer setSubject:@"Master Password site export"];
|
|
||||||
[composer setMessageBody:message isHTML:NO];
|
|
||||||
[composer addAttachmentData:[exportedSites dataUsingEncoding:NSUTF8StringEncoding] mimeType:@"text/plain"
|
|
||||||
fileName:[exportDateFormatter stringFromDate:[NSDate date]]];
|
|
||||||
[self.window.rootViewController presentModalViewController:composer animated:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)changeMP {
|
|
||||||
|
|
||||||
[PearlAlert showAlertWithTitle:@"Changing Master Password"
|
|
||||||
message:
|
|
||||||
@"This will allow you to log in with a different master password.\n\n"
|
|
||||||
@"Note that you will only see the sites and passwords for the master password you log in with.\n"
|
|
||||||
@"If you log in with a different master password, your current sites will be unavailable.\n\n"
|
|
||||||
@"You can always change back to your current master password later.\n"
|
|
||||||
@"Your current sites and passwords will then become available again."
|
|
||||||
viewStyle:UIAlertViewStyleDefault
|
|
||||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
|
||||||
if (buttonIndex == [alert cancelButtonIndex])
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.activeUser.keyID = nil;
|
|
||||||
[self signOut];
|
|
||||||
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointChangeMP];
|
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointChangeMP
|
|
||||||
attributes:nil];
|
|
||||||
}
|
|
||||||
cancelTitle:[PearlStrings get].commonButtonAbort
|
|
||||||
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - PearlConfigDelegate
|
|
||||||
|
|
||||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value {
|
|
||||||
|
|
||||||
[self checkConfig];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - UIApplicationDelegate
|
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
|
|
||||||
[[[NSBundle mainBundle] mutableInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"];
|
[[[NSBundle mainBundle] mutableInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"];
|
||||||
[[[NSBundle mainBundle] mutableLocalizedInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"];
|
[[[NSBundle mainBundle] mutableLocalizedInfoDictionary] setObject:@"Master Password" forKey:@"CFBundleDisplayName"];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
|
||||||
//#ifndef DEBUG
|
|
||||||
@try {
|
|
||||||
NSString *testFlightToken = [self testFlightToken];
|
|
||||||
if ([testFlightToken length]) {
|
|
||||||
dbg(@"Initializing TestFlight");
|
|
||||||
[TestFlight addCustomEnvironmentInformation:@"Anonymous" forKey:@"username"];
|
|
||||||
#ifdef ADHOC
|
|
||||||
[TestFlight setDeviceIdentifier:[(id)[UIDevice currentDevice] uniqueIdentifier]];
|
|
||||||
#else
|
|
||||||
[TestFlight setDeviceIdentifier:[PearlKeyChain deviceIdentifier]];
|
|
||||||
#endif
|
|
||||||
[TestFlight setOptions:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
||||||
[NSNumber numberWithBool:NO], @"logToConsole",
|
|
||||||
[NSNumber numberWithBool:NO], @"logToSTDERR",
|
|
||||||
nil]];
|
|
||||||
[TestFlight takeOff:testFlightToken];
|
|
||||||
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
|
||||||
PearlLogLevel level = PearlLogLevelInfo;
|
|
||||||
if ([[MPiOSConfig get].sendDebugInfo boolValue])
|
|
||||||
level = PearlLogLevelDebug;
|
|
||||||
|
|
||||||
if (message.level >= level)
|
|
||||||
TFLog(@"%@", message);
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}];
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointLaunched];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@catch (id exception) {
|
|
||||||
err(@"TestFlight: %@", exception);
|
|
||||||
}
|
|
||||||
@try {
|
|
||||||
NSString *crashlyticsAPIKey = [self crashlyticsAPIKey];
|
|
||||||
if ([crashlyticsAPIKey length]) {
|
|
||||||
dbg(@"Initializing Crashlytics");
|
|
||||||
//[Crashlytics sharedInstance].debugMode = YES;
|
|
||||||
[[Crashlytics sharedInstance] setObjectValue:@"Anonymous" forKey:@"username"];
|
|
||||||
[[Crashlytics sharedInstance] setObjectValue:[PearlKeyChain deviceIdentifier] forKey:@"deviceIdentifier"];
|
|
||||||
[Crashlytics startWithAPIKey:crashlyticsAPIKey afterDelay:0];
|
|
||||||
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
|
||||||
PearlLogLevel level = PearlLogLevelInfo;
|
|
||||||
if ([[MPiOSConfig get].sendDebugInfo boolValue])
|
|
||||||
level = PearlLogLevelDebug;
|
|
||||||
|
|
||||||
if (message.level >= level)
|
|
||||||
CLSLog(@"%@", message);
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@catch (id exception) {
|
|
||||||
err(@"Crashlytics: %@", exception);
|
|
||||||
}
|
|
||||||
@try {
|
|
||||||
NSString *localyticsKey = [self localyticsKey];
|
|
||||||
if ([localyticsKey length]) {
|
|
||||||
dbg(@"Initializing Localytics");
|
|
||||||
[[LocalyticsSession sharedLocalyticsSession] startSession:localyticsKey];
|
|
||||||
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
|
||||||
if (message.level >= PearlLogLevelError)
|
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:@"Problem" attributes:
|
|
||||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
|
||||||
[message levelDescription],
|
|
||||||
@"level",
|
|
||||||
message.message,
|
|
||||||
@"message",
|
|
||||||
nil]];
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@catch (id exception) {
|
|
||||||
err(@"Localytics exception: %@", exception);
|
|
||||||
}
|
|
||||||
//#endif
|
|
||||||
});
|
|
||||||
|
|
||||||
@try {
|
@try {
|
||||||
NSString *apptentiveAPIKey = [self apptentiveAPIKey];
|
NSString *testFlightToken = [self testFlightToken];
|
||||||
if ([apptentiveAPIKey length]) {
|
if ([testFlightToken length]) {
|
||||||
dbg(@"Initializing Apptentive");
|
inf(@"Initializing TestFlight");
|
||||||
|
[TestFlight addCustomEnvironmentInformation:@"Anonymous" forKey:@"username"];
|
||||||
|
#ifdef ADHOC
|
||||||
|
[TestFlight setDeviceIdentifier:[(id)[UIDevice currentDevice] uniqueIdentifier]];
|
||||||
|
#else
|
||||||
|
[TestFlight setDeviceIdentifier:[PearlKeyChain deviceIdentifier]];
|
||||||
|
#endif
|
||||||
|
[TestFlight setOptions:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[NSNumber numberWithBool:NO], @"logToConsole",
|
||||||
|
[NSNumber numberWithBool:NO], @"logToSTDERR",
|
||||||
|
nil]];
|
||||||
|
[TestFlight takeOff:testFlightToken];
|
||||||
|
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
||||||
|
PearlLogLevel level = PearlLogLevelWarn;
|
||||||
|
if ([[MPiOSConfig get].sendInfo boolValue])
|
||||||
|
level = PearlLogLevelInfo;
|
||||||
|
|
||||||
ATConnect *connection = [ATConnect sharedConnection];
|
if (message.level >= level)
|
||||||
[connection setApiKey:apptentiveAPIKey];
|
TFLog(@"%@", message);
|
||||||
[connection setShouldTakeScreenshot:NO];
|
|
||||||
[connection addAdditionalInfoToFeedback:[PearlInfoPlist get].CFBundleVersion withKey:@"CFBundleVersion"];
|
return YES;
|
||||||
[connection addAdditionalInfoToFeedback:[PearlKeyChain deviceIdentifier] withKey:@"deviceIdentifier"];
|
}];
|
||||||
[connection addAdditionalInfoToFeedback:@"Anonymous" withKey:@"username"];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@catch (NSException *exception) {
|
@catch (id exception) {
|
||||||
err(@"Apptentive: %@", exception);
|
err(@"TestFlight: %@", exception);
|
||||||
|
}
|
||||||
|
@try {
|
||||||
|
NSString *crashlyticsAPIKey = [self crashlyticsAPIKey];
|
||||||
|
if ([crashlyticsAPIKey length]) {
|
||||||
|
inf(@"Initializing Crashlytics");
|
||||||
|
[Crashlytics sharedInstance].debugMode = YES;
|
||||||
|
[[Crashlytics sharedInstance] setObjectValue:@"Anonymous" forKey:@"username"];
|
||||||
|
[[Crashlytics sharedInstance] setObjectValue:[PearlKeyChain deviceIdentifier] forKey:@"deviceIdentifier"];
|
||||||
|
[Crashlytics startWithAPIKey:crashlyticsAPIKey afterDelay:0];
|
||||||
|
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
||||||
|
PearlLogLevel level = PearlLogLevelWarn;
|
||||||
|
if ([[MPiOSConfig get].sendInfo boolValue])
|
||||||
|
level = PearlLogLevelInfo;
|
||||||
|
|
||||||
|
if (message.level >= level)
|
||||||
|
CLSLog(@"%@", message);
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@catch (id exception) {
|
||||||
|
err(@"Crashlytics: %@", exception);
|
||||||
|
}
|
||||||
|
@try {
|
||||||
|
NSString *localyticsKey = [self localyticsKey];
|
||||||
|
if ([localyticsKey length]) {
|
||||||
|
inf(@"Initializing Localytics");
|
||||||
|
[[LocalyticsSession sharedLocalyticsSession] startSession:localyticsKey];
|
||||||
|
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
||||||
|
if (message.level >= PearlLogLevelWarn)
|
||||||
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:@"Problem" attributes:
|
||||||
|
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[message levelDescription],
|
||||||
|
@"level",
|
||||||
|
message.message,
|
||||||
|
@"message",
|
||||||
|
nil]];
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@catch (id exception) {
|
||||||
|
err(@"Localytics exception: %@", 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)];
|
||||||
@ -290,26 +157,27 @@
|
|||||||
[[UIToolbar appearance] setBackgroundImage:toolBarImage forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
|
[[UIToolbar appearance] setBackgroundImage:toolBarImage forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
UIImage *minImage = [[UIImage imageNamed:@"slider-minimum.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
|
UIImage *minImage = [[UIImage imageNamed:@"slider-minimum.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
|
||||||
UIImage *maxImage = [[UIImage imageNamed:@"slider-maximum.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
|
UIImage *maxImage = [[UIImage imageNamed:@"slider-maximum.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
|
||||||
UIImage *thumbImage = [UIImage imageNamed:@"slider-handle.png"];
|
UIImage *thumbImage = [UIImage imageNamed:@"slider-handle.png"];
|
||||||
|
|
||||||
[[UISlider appearance] setMaximumTrackImage:maxImage forState:UIControlStateNormal];
|
[[UISlider appearance] setMaximumTrackImage:maxImage forState:UIControlStateNormal];
|
||||||
[[UISlider appearance] setMinimumTrackImage:minImage forState:UIControlStateNormal];
|
[[UISlider appearance] setMinimumTrackImage:minImage forState:UIControlStateNormal];
|
||||||
[[UISlider appearance] setThumbImage:thumbImage forState:UIControlStateNormal];
|
[[UISlider appearance] setThumbImage:thumbImage forState:UIControlStateNormal];
|
||||||
|
|
||||||
UIImage *segmentSelected = [[UIImage imageNamed:@"segcontrol_sel.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
|
UIImage *segmentSelected = [[UIImage imageNamed:@"segcontrol_sel.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
|
||||||
UIImage *segmentUnselected = [[UIImage imageNamed:@"segcontrol_uns.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
|
UIImage *segmentUnselected = [[UIImage imageNamed:@"segcontrol_uns.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
|
||||||
UIImage *segmentSelectedUnselected = [UIImage imageNamed:@"segcontrol_sel-uns.png"];
|
UIImage *segmentSelectedUnselected = [UIImage imageNamed:@"segcontrol_sel-uns.png"];
|
||||||
UIImage *segUnselectedSelected = [UIImage imageNamed:@"segcontrol_uns-sel.png"];
|
UIImage *segUnselectedSelected = [UIImage imageNamed:@"segcontrol_uns-sel.png"];
|
||||||
UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.png"];
|
UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.png"];
|
||||||
|
|
||||||
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
||||||
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
|
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
|
||||||
|
|
||||||
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
||||||
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected forLeftSegmentState:UIControlStateSelected rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected forLeftSegmentState:UIControlStateSelected rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
||||||
[[UISegmentedControl appearance] setDividerImage:segUnselectedSelected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateSelected barMetrics:UIBarMetricsDefault];*/
|
[[UISegmentedControl appearance] setDividerImage:segUnselectedSelected forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
|
||||||
|
*/
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPNotificationSignedOut object:nil queue:nil
|
[[NSNotificationCenter defaultCenter] addObserverForName:MPNotificationSignedOut object:nil queue:nil
|
||||||
usingBlock:^(NSNotification *note) {
|
usingBlock:^(NSNotification *note) {
|
||||||
@ -334,7 +202,13 @@ UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.
|
|||||||
|
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
|
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
|
||||||
|
|
||||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
[super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||||
|
|
||||||
|
inf(@"Started up with device identifier: %@", [PearlKeyChain deviceIdentifier]);
|
||||||
|
[TestFlight passCheckpoint:MPCheckpointLaunched];
|
||||||
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointLaunched];
|
||||||
|
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
|
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
|
||||||
@ -407,6 +281,7 @@ UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.
|
|||||||
|
|
||||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||||
|
|
||||||
|
inf(@"Re-activated");
|
||||||
[[MPAppDelegate get] checkConfig];
|
[[MPAppDelegate get] checkConfig];
|
||||||
|
|
||||||
if ([[MPiOSConfig get].showQuickStart boolValue])
|
if ([[MPiOSConfig get].showQuickStart boolValue])
|
||||||
@ -447,6 +322,7 @@ UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.
|
|||||||
|
|
||||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||||
|
|
||||||
|
inf(@"Will deactivate");
|
||||||
[self saveContext];
|
[self saveContext];
|
||||||
|
|
||||||
if (![[MPiOSConfig get].rememberLogin boolValue])
|
if (![[MPiOSConfig get].rememberLogin boolValue])
|
||||||
@ -455,6 +331,159 @@ UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.
|
|||||||
[TestFlight passCheckpoint:MPCheckpointDeactivated];
|
[TestFlight passCheckpoint:MPCheckpointDeactivated];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma - mark Behavior
|
||||||
|
|
||||||
|
- (void)checkConfig {
|
||||||
|
|
||||||
|
if ([[MPConfig get].iCloud boolValue] != [self.storeManager iCloudEnabled])
|
||||||
|
[self.storeManager useiCloudStore:[[MPConfig get].iCloud boolValue] alertUser:YES];
|
||||||
|
if ([[MPiOSConfig get].sendInfo boolValue]) {
|
||||||
|
if ([PearlLogger get].autoprintLevel > PearlLogLevelInfo)
|
||||||
|
[PearlLogger get].autoprintLevel = PearlLogLevelInfo;
|
||||||
|
|
||||||
|
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].rememberLogin boolValue] forKey:@"rememberLogin"];
|
||||||
|
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].iCloud boolValue] 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].showQuickStart 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"];
|
||||||
|
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[MPConfig get].rememberLogin boolValue]? @"YES": @"NO" forKey:@"rememberLogin"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[MPConfig get].iCloud boolValue]? @"YES": @"NO" forKey:@"iCloud"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[MPConfig get].iCloudDecided boolValue]? @"YES": @"NO" forKey:@"iCloudDecided"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[MPiOSConfig get].sendInfo boolValue]? @"YES": @"NO" forKey:@"sendInfo"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[MPiOSConfig get].helpHidden boolValue]? @"YES": @"NO" forKey:@"helpHidden"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[MPiOSConfig get].showQuickStart boolValue]? @"YES": @"NO" forKey:@"showQuickStart"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].firstRun boolValue]? @"YES": @"NO" forKey:@"firstRun"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].launchCount description] forKey:@"launchCount"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].askForReviews boolValue]? @"YES": @"NO" forKey:@"askForReviews"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[[PearlConfig get].reviewAfterLaunches description] forKey:@"reviewAfterLaunches"];
|
||||||
|
[TestFlight addCustomEnvironmentInformation:[PearlConfig get].reviewedVersion forKey:@"reviewedVersion"];
|
||||||
|
|
||||||
|
[TestFlight passCheckpoint:MPCheckpointConfig];
|
||||||
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointConfig attributes:
|
||||||
|
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[[MPConfig get].rememberLogin boolValue]
|
||||||
|
? @"YES": @"NO", @"rememberLogin",
|
||||||
|
[[MPConfig get].iCloud boolValue]? @"YES"
|
||||||
|
: @"NO", @"iCloud",
|
||||||
|
[[MPConfig get].iCloudDecided boolValue]
|
||||||
|
? @"YES": @"NO", @"iCloudDecided",
|
||||||
|
[[MPiOSConfig get].sendInfo boolValue]
|
||||||
|
? @"YES": @"NO", @"sendInfo",
|
||||||
|
[[MPiOSConfig get].helpHidden boolValue]
|
||||||
|
? @"YES": @"NO", @"helpHidden",
|
||||||
|
[[MPiOSConfig get].showQuickStart boolValue]
|
||||||
|
? @"YES": @"NO", @"showQuickStart",
|
||||||
|
[[PearlConfig get].firstRun boolValue]
|
||||||
|
? @"YES": @"NO", @"firstRun",
|
||||||
|
[[PearlConfig get].launchCount description], @"launchCount",
|
||||||
|
[[PearlConfig get].askForReviews boolValue]
|
||||||
|
? @"YES": @"NO", @"askForReviews",
|
||||||
|
[[PearlConfig get].reviewAfterLaunches description], @"reviewAfterLaunches",
|
||||||
|
[PearlConfig get].reviewedVersion, @"reviewedVersion",
|
||||||
|
nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)showGuide {
|
||||||
|
|
||||||
|
[self.navigationController performSegueWithIdentifier:@"MP_Guide" sender:self];
|
||||||
|
|
||||||
|
[TestFlight passCheckpoint:MPCheckpointShowGuide];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)export {
|
||||||
|
|
||||||
|
[PearlAlert showNotice:
|
||||||
|
@"This will export all your site names.\n\n"
|
||||||
|
@"You can open the export with a text editor to get an overview of all your sites.\n\n"
|
||||||
|
@"The file also acts as a personal backup of your site list in case you don't sync with iCloud/iTunes."
|
||||||
|
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||||
|
[PearlAlert showAlertWithTitle:@"Reveal Passwords?" message:
|
||||||
|
@"Would you like to make all your passwords visible in the export?\n\n"
|
||||||
|
@"A safe export will only include your stored passwords, in an encrypted manner, "
|
||||||
|
@"making the result safe from falling in the wrong hands.\n\n"
|
||||||
|
@"If all your passwords are shown and somebody else finds the export, "
|
||||||
|
@"they could gain access to all your sites!"
|
||||||
|
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||||
|
tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||||
|
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 0)
|
||||||
|
// Safe Export
|
||||||
|
[self exportShowPasswords:NO];
|
||||||
|
if (buttonIndex_ == [alert_ firstOtherButtonIndex] + 1)
|
||||||
|
// Safe Export
|
||||||
|
[self exportShowPasswords:YES];
|
||||||
|
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Safe Export", @"Show Passwords", nil];
|
||||||
|
} otherTitles:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)exportShowPasswords:(BOOL)showPasswords {
|
||||||
|
|
||||||
|
NSString *exportedSites = [self exportSitesShowingPasswords:showPasswords];
|
||||||
|
NSString *message;
|
||||||
|
if (showPasswords)
|
||||||
|
message = PearlString(
|
||||||
|
@"Export of %@'s Master Password sites with passwords visible.\n"
|
||||||
|
@"REMINDER: Make sure nobody else sees this file! All passwords are visible!\n",
|
||||||
|
self.activeUser.name);
|
||||||
|
else
|
||||||
|
message = PearlString(
|
||||||
|
@"Backup of %@'s Master Password sites.\n",
|
||||||
|
self.activeUser.name);
|
||||||
|
|
||||||
|
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||||
|
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'DD"];
|
||||||
|
|
||||||
|
MFMailComposeViewController *composer = [MFMailComposeViewController new];
|
||||||
|
[composer setMailComposeDelegate:self];
|
||||||
|
[composer setSubject:@"Master Password Export"];
|
||||||
|
[composer setMessageBody:message isHTML:NO];
|
||||||
|
[composer addAttachmentData:
|
||||||
|
[exportedSites dataUsingEncoding:NSUTF8StringEncoding] mimeType:@"text/plain"
|
||||||
|
fileName:PearlString(@"%@ (%@).mpsites",
|
||||||
|
self.activeUser.name,
|
||||||
|
[exportDateFormatter stringFromDate:[NSDate date]])];
|
||||||
|
[self.window.rootViewController presentModalViewController:composer animated:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)changeMP {
|
||||||
|
|
||||||
|
[PearlAlert showAlertWithTitle:@"Changing Master Password"
|
||||||
|
message:
|
||||||
|
@"If you continue, you'll be able to set a new master password.\n\n"
|
||||||
|
@"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."
|
||||||
|
viewStyle:UIAlertViewStyleDefault
|
||||||
|
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||||
|
if (buttonIndex == [alert cancelButtonIndex])
|
||||||
|
return;
|
||||||
|
|
||||||
|
inf(@"Unsetting master password for: %@.", self.activeUser.userID);
|
||||||
|
self.activeUser.keyID = nil;
|
||||||
|
[self forgetSavedKeyFor:self.activeUser];
|
||||||
|
[self signOut];
|
||||||
|
|
||||||
|
[TestFlight passCheckpoint:MPCheckpointChangeMP];
|
||||||
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointChangeMP
|
||||||
|
attributes:nil];
|
||||||
|
}
|
||||||
|
cancelTitle:[PearlStrings get].commonButtonAbort
|
||||||
|
otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - PearlConfigDelegate
|
||||||
|
|
||||||
|
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)value {
|
||||||
|
|
||||||
|
[self checkConfig];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - MFMailComposeViewControllerDelegate
|
#pragma mark - MFMailComposeViewControllerDelegate
|
||||||
|
|
||||||
- (void)mailComposeController:(MFMailComposeViewController *)controller
|
- (void)mailComposeController:(MFMailComposeViewController *)controller
|
||||||
@ -566,25 +595,6 @@ UIImage *segmentUnselectedUnselected = [UIImage imageNamed:@"segcontrol_uns-uns.
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Apptentive
|
|
||||||
|
|
||||||
|
|
||||||
- (NSDictionary *)apptentiveInfo {
|
|
||||||
|
|
||||||
static NSDictionary *apptentiveInfo = nil;
|
|
||||||
if (apptentiveInfo == nil)
|
|
||||||
apptentiveInfo = [[NSDictionary alloc] initWithContentsOfURL:
|
|
||||||
[[NSBundle mainBundle] URLForResource:@"Apptentive" withExtension:@"plist"]];
|
|
||||||
|
|
||||||
return apptentiveInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)apptentiveAPIKey {
|
|
||||||
|
|
||||||
return NSNullToNil([[self apptentiveInfo] valueForKeyPath:@"API Key"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Localytics
|
#pragma mark - Localytics
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,15 +24,22 @@
|
|||||||
[self.scrollView autoSizeContent];
|
[self.scrollView autoSizeContent];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Guide will appear.");
|
||||||
|
[super viewWillAppear:animated];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated {
|
- (void)viewDidAppear:(BOOL)animated {
|
||||||
|
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:animated? UIStatusBarAnimationSlide: UIStatusBarAnimationNone];
|
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:animated? UIStatusBarAnimationSlide: UIStatusBarAnimationNone];
|
||||||
|
|
||||||
[super viewDidAppear:animated];
|
[super viewDidAppear:animated];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Guide will disappear.");
|
||||||
[super viewWillDisappear:animated];
|
[super viewWillDisappear:animated];
|
||||||
|
|
||||||
[MPiOSConfig get].showQuickStart = [NSNumber numberWithBool:NO];
|
[MPiOSConfig get].showQuickStart = [NSNumber numberWithBool:NO];
|
||||||
|
@ -6,11 +6,12 @@
|
|||||||
// Copyright (c) 2011 Lyndir. All rights reserved.
|
// Copyright (c) 2011 Lyndir. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#import <MessageUI/MessageUI.h>
|
||||||
#import "MPTypeViewController.h"
|
#import "MPTypeViewController.h"
|
||||||
#import "MPElementEntity.h"
|
#import "MPElementEntity.h"
|
||||||
#import "MPSearchDelegate.h"
|
#import "MPSearchDelegate.h"
|
||||||
|
|
||||||
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPSearchResultsDelegate, UIWebViewDelegate>
|
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPSearchResultsDelegate, UIWebViewDelegate, MFMailComposeViewControllerDelegate>
|
||||||
|
|
||||||
@property (strong, nonatomic) MPElementEntity *activeElement;
|
@property (strong, nonatomic) MPElementEntity *activeElement;
|
||||||
@property (strong, nonatomic) IBOutlet MPSearchDelegate *searchResultsController;
|
@property (strong, nonatomic) IBOutlet MPSearchDelegate *searchResultsController;
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#import "MPAppDelegate.h"
|
#import "MPAppDelegate.h"
|
||||||
#import "MPAppDelegate_Key.h"
|
#import "MPAppDelegate_Key.h"
|
||||||
#import "MPAppDelegate_Store.h"
|
#import "MPAppDelegate_Store.h"
|
||||||
#import "ATConnect.h"
|
|
||||||
#import "LocalyticsSession.h"
|
#import "LocalyticsSession.h"
|
||||||
|
|
||||||
|
|
||||||
@ -66,8 +65,21 @@
|
|||||||
((MPTypeViewController *)[segue destinationViewController]).delegate = self;
|
((MPTypeViewController *)[segue destinationViewController]).delegate = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
|
||||||
|
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"ui_background"]];
|
||||||
|
|
||||||
|
self.contentField.font = [UIFont fontWithName:@"Exo-Black" size:self.contentField.font.pointSize];
|
||||||
|
|
||||||
|
self.alertBody.text = nil;
|
||||||
|
self.contentTipEditIcon.hidden = YES;
|
||||||
|
|
||||||
|
[super viewDidLoad];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Main will appear.");
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:animated? UIStatusBarAnimationSlide: UIStatusBarAnimationNone];
|
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:animated? UIStatusBarAnimationSlide: UIStatusBarAnimationNone];
|
||||||
|
|
||||||
if (![MPAppDelegate get].activeUser)
|
if (![MPAppDelegate get].activeUser)
|
||||||
@ -83,7 +95,7 @@
|
|||||||
|
|
||||||
[self setHelpHidden:[[MPiOSConfig get].helpHidden boolValue] animated:animated];
|
[self setHelpHidden:[[MPiOSConfig get].helpHidden boolValue] animated:animated];
|
||||||
[self updateAnimated:animated];
|
[self updateAnimated:animated];
|
||||||
|
|
||||||
[super viewWillAppear:animated];
|
[super viewWillAppear:animated];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,16 +122,10 @@
|
|||||||
[super viewDidAppear:animated];
|
[super viewDidAppear:animated];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidLoad {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
||||||
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"ui_background"]];
|
inf(@"Main will disappear.");
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
self.contentField.font = [UIFont fontWithName:@"Exo-Black" size:self.contentField.font.pointSize];
|
|
||||||
|
|
||||||
self.alertBody.text = nil;
|
|
||||||
self.contentTipEditIcon.hidden = YES;
|
|
||||||
|
|
||||||
[super viewDidLoad];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidUnload {
|
- (void)viewDidUnload {
|
||||||
@ -280,6 +286,7 @@
|
|||||||
if (!self.activeElement)
|
if (!self.activeElement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
inf(@"Copying password for: %@", self.activeElement.name);
|
||||||
[UIPasteboard generalPasteboard].string = [self.activeElement.content description];
|
[UIPasteboard generalPasteboard].string = [self.activeElement.content description];
|
||||||
|
|
||||||
[self showContentTip:@"Copied!" withIcon:nil];
|
[self showContentTip:@"Copied!" withIcon:nil];
|
||||||
@ -303,14 +310,15 @@
|
|||||||
@"You will then need to update your account's old password to this newly generated password.\n\n"
|
@"You will then need to update your account's old password to this newly generated password.\n\n"
|
||||||
@"You can reset the counter by holding down on this button."
|
@"You can reset the counter by holding down on this button."
|
||||||
do:^{
|
do:^{
|
||||||
|
inf(@"Incrementing password counter for: %@", self.activeElement.name);
|
||||||
++((MPElementGeneratedEntity *)self.activeElement).counter;
|
++((MPElementGeneratedEntity *)self.activeElement).counter;
|
||||||
}];
|
|
||||||
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointIncrementPasswordCounter];
|
[TestFlight passCheckpoint:MPCheckpointIncrementPasswordCounter];
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointIncrementPasswordCounter
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointIncrementPasswordCounter
|
||||||
attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
NSStringFromMPElementType(self.activeElement.type), @"type",
|
NSStringFromMPElementType(self.activeElement.type), @"type",
|
||||||
nil]];
|
nil]];
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)resetPasswordCounter:(UILongPressGestureRecognizer *)sender {
|
- (IBAction)resetPasswordCounter:(UILongPressGestureRecognizer *)sender {
|
||||||
@ -330,14 +338,15 @@
|
|||||||
@"If you continue, the site's password will change back to its original value. "
|
@"If you continue, the site's password will change back to its original value. "
|
||||||
@"You will then need to update your account's password back to this original value."
|
@"You will then need to update your account's password back to this original value."
|
||||||
do:^{
|
do:^{
|
||||||
|
inf(@"Resetting password counter for: %@", self.activeElement.name);
|
||||||
((MPElementGeneratedEntity *)self.activeElement).counter = 1;
|
((MPElementGeneratedEntity *)self.activeElement).counter = 1;
|
||||||
}];
|
|
||||||
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointResetPasswordCounter];
|
[TestFlight passCheckpoint:MPCheckpointResetPasswordCounter];
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointResetPasswordCounter
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointResetPasswordCounter
|
||||||
attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
NSStringFromMPElementType(self.activeElement.type), @"type",
|
NSStringFromMPElementType(self.activeElement.type), @"type",
|
||||||
nil]];
|
nil]];
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)changeElementWithWarning:(NSString *)warning do:(void (^)(void))task; {
|
- (void)changeElementWithWarning:(NSString *)warning do:(void (^)(void))task; {
|
||||||
@ -376,13 +385,14 @@
|
|||||||
if (self.activeElement.type & MPElementTypeClassStored) {
|
if (self.activeElement.type & MPElementTypeClassStored) {
|
||||||
self.contentField.enabled = YES;
|
self.contentField.enabled = YES;
|
||||||
[self.contentField becomeFirstResponder];
|
[self.contentField becomeFirstResponder];
|
||||||
}
|
|
||||||
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointEditPassword];
|
[TestFlight passCheckpoint:MPCheckpointEditPassword];
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointEditPassword
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointEditPassword
|
||||||
attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
NSStringFromMPElementType(self.activeElement.type), @"type",
|
NSStringFromMPElementType(
|
||||||
nil]];
|
self.activeElement.type), @"type",
|
||||||
|
nil]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)closeAlert {
|
- (IBAction)closeAlert {
|
||||||
@ -406,37 +416,88 @@
|
|||||||
|
|
||||||
switch (buttonIndex - [sheet firstOtherButtonIndex]) {
|
switch (buttonIndex - [sheet firstOtherButtonIndex]) {
|
||||||
case 0: {
|
case 0: {
|
||||||
|
inf(@"Action: Toggle Help");
|
||||||
[self toggleHelpAnimated:YES];
|
[self toggleHelpAnimated:YES];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
|
inf(@"Action: FAQ");
|
||||||
[self setHelpChapter:@"faq"];
|
[self setHelpChapter:@"faq"];
|
||||||
[self setHelpHidden:NO animated:YES];
|
[self setHelpHidden:NO animated:YES];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
|
inf(@"Action: Guide");
|
||||||
[[MPAppDelegate get] showGuide];
|
[[MPAppDelegate get] showGuide];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
|
inf(@"Action: Preferences");
|
||||||
[self performSegueWithIdentifier:@"UserProfile" sender:self];
|
[self performSegueWithIdentifier:@"UserProfile" sender:self];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef ADHOC
|
#ifdef ADHOC
|
||||||
case 4: {
|
case 4: {
|
||||||
|
inf(@"Action: Feedback via TestFlight");
|
||||||
[TestFlight openFeedbackView];
|
[TestFlight openFeedbackView];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5:
|
case 5:
|
||||||
#else
|
#else
|
||||||
case 4: {
|
case 4: {
|
||||||
ATConnect *connection = [ATConnect sharedConnection];
|
inf(@"Action: Feedback via Mail");
|
||||||
[connection presentFeedbackControllerFromViewController:self];
|
if (![MFMailComposeViewController canSendMail])
|
||||||
|
[PearlAlert showAlertWithTitle:@"Feedback"
|
||||||
|
message:
|
||||||
|
@"We'd love to hear what you think!\n\n"
|
||||||
|
@"Please send any comments or reports to:\n"
|
||||||
|
@"masterpassword@lyndir.com"
|
||||||
|
viewStyle:UIAlertViewStyleDefault
|
||||||
|
initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay
|
||||||
|
otherTitles:nil];
|
||||||
|
|
||||||
|
else {
|
||||||
|
[PearlAlert showAlertWithTitle:@"Feedback"
|
||||||
|
message:
|
||||||
|
@"We'd love to hear what you think!\n\n"
|
||||||
|
@"If you're having trouble, it may help us if you can first reproduce the problem "
|
||||||
|
@"and then include log files in your message."
|
||||||
|
viewStyle:UIAlertViewStyleDefault
|
||||||
|
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||||
|
MFMailComposeViewController *composer = [MFMailComposeViewController new];
|
||||||
|
[composer setMailComposeDelegate:self];
|
||||||
|
[composer setToRecipients:[NSArray arrayWithObject:@"Master Password Development <masterpassword@lyndir.com>"]];
|
||||||
|
[composer setSubject:PearlString(@"Feedback for Master Password [%@]", [[PearlKeyChain deviceIdentifier] stringByDeletingMatchesOf:@"-.*"])];
|
||||||
|
[composer setMessageBody:
|
||||||
|
PearlString(
|
||||||
|
@"\n\n\n"
|
||||||
|
@"--\n"
|
||||||
|
@"%@\n"
|
||||||
|
@"Master Password %@, build %@",
|
||||||
|
[MPAppDelegate get].activeUser.name,
|
||||||
|
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||||
|
[PearlInfoPlist get].CFBundleVersion)
|
||||||
|
isHTML:NO];
|
||||||
|
|
||||||
|
if (buttonIndex_ == [alert_ firstOtherButtonIndex]) {
|
||||||
|
PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug: PearlLogLevelInfo;
|
||||||
|
[composer addAttachmentData:[[[PearlLogger get] formatMessagesWithLevel:logLevel] dataUsingEncoding:NSUTF8StringEncoding]
|
||||||
|
mimeType:@"text/plain"
|
||||||
|
fileName:PearlString(@"%@-%@.log",
|
||||||
|
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]],
|
||||||
|
[PearlKeyChain deviceIdentifier])];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self presentModalViewController:composer animated:YES];
|
||||||
|
}
|
||||||
|
cancelTitle:nil otherTitles:@"Include Logs", @"No Logs", nil];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5:
|
case 5:
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
inf(@"Action: Sign out");
|
||||||
[[MPAppDelegate get] signOut];
|
[[MPAppDelegate get] signOut];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -448,6 +509,17 @@
|
|||||||
[self isHelpVisible]? @"Hide Help": @"Show Help", @"FAQ", @"Tutorial", @"Preferences", @"Feedback", @"Sign Out", nil];
|
[self isHelpVisible]? @"Hide Help": @"Show Help", @"FAQ", @"Tutorial", @"Preferences", @"Feedback", @"Sign Out", nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result
|
||||||
|
error:(NSError *)error {
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
err(@"Feedback composer error: %@, result: %d", error, result);
|
||||||
|
else
|
||||||
|
inf(@"Feedback composer result: %d", result);
|
||||||
|
|
||||||
|
[controller dismissViewControllerAnimated:YES completion:nil];
|
||||||
|
}
|
||||||
|
|
||||||
- (MPElementType)selectedType {
|
- (MPElementType)selectedType {
|
||||||
|
|
||||||
return self.activeElement.type;
|
return self.activeElement.type;
|
||||||
@ -485,6 +557,8 @@
|
|||||||
|
|
||||||
- (void)didSelectElement:(MPElementEntity *)element {
|
- (void)didSelectElement:(MPElementEntity *)element {
|
||||||
|
|
||||||
|
inf(@"Selected: %@", element.name);
|
||||||
|
|
||||||
[self closeAlert];
|
[self closeAlert];
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
@ -516,10 +590,10 @@
|
|||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPNotificationElementUsed object:self.activeElement];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPNotificationElementUsed object:self.activeElement];
|
||||||
[TestFlight passCheckpoint:PearlString(MPCheckpointUseType @"_%@", NSStringFromMPElementType(self.activeElement.type))];
|
[TestFlight passCheckpoint:PearlString(MPCheckpointUseType @"_%@", NSStringFromMPElementType(self.activeElement.type))];
|
||||||
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointUseType
|
[[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointUseType attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
attributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
NSStringFromMPElementType(
|
||||||
NSStringFromMPElementType(self.activeElement.type), @"type",
|
self.activeElement.type), @"type",
|
||||||
nil]];
|
nil]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self updateAnimated:YES];
|
[self updateAnimated:YES];
|
||||||
@ -555,6 +629,7 @@
|
|||||||
navigationType:(UIWebViewNavigationType)navigationType {
|
navigationType:(UIWebViewNavigationType)navigationType {
|
||||||
|
|
||||||
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
|
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
|
||||||
|
inf(@"External link: %@", [request URL]);
|
||||||
[TestFlight passCheckpoint:MPCheckpointExternalLink];
|
[TestFlight passCheckpoint:MPCheckpointExternalLink];
|
||||||
|
|
||||||
[[UIApplication sharedApplication] openURL:[request URL]];
|
[[UIApplication sharedApplication] openURL:[request URL]];
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Preferences will appear");
|
||||||
[self.avatarsView autoSizeContent];
|
[self.avatarsView autoSizeContent];
|
||||||
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||||
if (subview.tag && ((UIControl *)subview).selected) {
|
if (subview.tag && ((UIControl *)subview).selected) {
|
||||||
@ -79,6 +80,12 @@
|
|||||||
[super viewWillAppear:animated];
|
[super viewWillAppear:animated];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Preferences will disappear");
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
||||||
|
|
||||||
return (interfaceOrientation == UIInterfaceOrientationPortrait);
|
return (interfaceOrientation == UIInterfaceOrientationPortrait);
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
|
|
||||||
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
|
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
|
||||||
|
|
||||||
|
dbg(@"Search ended with: %@", controller.searchBar.text);
|
||||||
controller.searchBar.prompt = nil;
|
controller.searchBar.prompt = nil;
|
||||||
controller.searchBar.searchResultsButtonSelected = NO;
|
controller.searchBar.searchResultsButtonSelected = NO;
|
||||||
}
|
}
|
||||||
@ -345,6 +346,8 @@ forRowAtIndexPath:(NSIndexPath *)indexPath {
|
|||||||
if (editingStyle == UITableViewCellEditingStyleDelete)
|
if (editingStyle == UITableViewCellEditingStyleDelete)
|
||||||
[self.fetchedResultsController.managedObjectContext performBlock:^{
|
[self.fetchedResultsController.managedObjectContext performBlock:^{
|
||||||
MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath];
|
MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath];
|
||||||
|
|
||||||
|
inf(@"Deleting element: %@", element.name);
|
||||||
[self.fetchedResultsController.managedObjectContext deleteObject:element];
|
[self.fetchedResultsController.managedObjectContext deleteObject:element];
|
||||||
|
|
||||||
[TestFlight passCheckpoint:MPCheckpointDeleteElement];
|
[TestFlight passCheckpoint:MPCheckpointDeleteElement];
|
||||||
|
@ -23,7 +23,10 @@
|
|||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Type selection will appear");
|
||||||
self.recommendedTipContainer.alpha = 0;
|
self.recommendedTipContainer.alpha = 0;
|
||||||
|
|
||||||
|
[super viewWillAppear:animated];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated {
|
- (void)viewDidAppear:(BOOL)animated {
|
||||||
@ -51,6 +54,12 @@
|
|||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Type selection will disappear");
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -142,6 +142,7 @@
|
|||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Lock screen will appear");
|
||||||
self.selectedUser = nil;
|
self.selectedUser = nil;
|
||||||
[self updateUsers];
|
[self updateUsers];
|
||||||
|
|
||||||
@ -157,6 +158,7 @@
|
|||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
|
||||||
|
inf(@"Lock screen will disappear");
|
||||||
[super viewWillDisappear:animated];
|
[super viewWillDisappear:animated];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
@interface MPiOSConfig : MPConfig
|
@interface MPiOSConfig : MPConfig
|
||||||
|
|
||||||
@property (nonatomic, retain) NSNumber *sendDebugInfo;
|
@property (nonatomic, retain) NSNumber *sendInfo;
|
||||||
@property (nonatomic, retain) NSNumber *helpHidden;
|
@property (nonatomic, retain) NSNumber *helpHidden;
|
||||||
@property (nonatomic, retain) NSNumber *showQuickStart;
|
@property (nonatomic, retain) NSNumber *showQuickStart;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
@implementation MPiOSConfig
|
@implementation MPiOSConfig
|
||||||
@dynamic sendDebugInfo, helpHidden, showQuickStart;
|
@dynamic sendInfo, helpHidden, showQuickStart;
|
||||||
|
|
||||||
- (id)init {
|
- (id)init {
|
||||||
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
return self;
|
return self;
|
||||||
|
|
||||||
[self.defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
|
[self.defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(sendDebugInfo)),
|
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(sendInfo)),
|
||||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(helpHidden)),
|
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(helpHidden)),
|
||||||
[NSNumber numberWithBool:YES], NSStringFromSelector(@selector(showQuickStart)),
|
[NSNumber numberWithBool:YES], NSStringFromSelector(@selector(showQuickStart)),
|
||||||
@"510296984", NSStringFromSelector(@selector(iTunesID)),
|
@"510296984", NSStringFromSelector(@selector(iTunesID)),
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
<key>Title</key>
|
<key>Title</key>
|
||||||
<string>Send Diagnostic Info</string>
|
<string>Send Diagnostic Info</string>
|
||||||
<key>Key</key>
|
<key>Key</key>
|
||||||
<string>sendDebugInfo</string>
|
<string>sendInfo</string>
|
||||||
<key>DefaultValue</key>
|
<key>DefaultValue</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
|
Loading…
Reference in New Issue
Block a user