Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ed6b93736 | ||
|
|
56a515c5ea | ||
|
|
15ac7a2dbf | ||
|
|
c5c7999753 | ||
|
|
bb58ed0169 | ||
|
|
4545a5c745 | ||
|
|
da8c7064fe | ||
|
|
d9bd604436 | ||
|
|
c99252809d | ||
|
|
d704f451a3 | ||
|
|
2c9ab5d153 | ||
|
|
d5d33da12f | ||
|
|
cbef1a611b | ||
|
|
0a1f215a1a | ||
|
|
907d2a8ca6 |
2
platform-darwin/External/InAppSettingsKit
vendored
2
platform-darwin/External/InAppSettingsKit
vendored
Submodule platform-darwin/External/InAppSettingsKit updated: b58b72563a...2dcb598d18
2
platform-darwin/External/Pearl
vendored
2
platform-darwin/External/Pearl
vendored
Submodule platform-darwin/External/Pearl updated: 3ceb601ba4...5e5eaa1344
@@ -19,7 +19,9 @@
|
||||
93D3932889B6B4206E66A6D6 /* PearlEMail.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */; };
|
||||
93D39392DEDA376F93C6C718 /* MPCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39BAA71DE51B4D8A1286C /* MPCell.m */; };
|
||||
93D3939661CE37180AF7CD6A /* MPStoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3957D76F71A652716EECC /* MPStoreViewController.m */; };
|
||||
93D393AA69A1193401160418 /* UIView+AlphaScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39488AB33616661725929 /* UIView+AlphaScale.m */; };
|
||||
93D393DB5325820241BA90A7 /* PearlSizedTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39A4759186F6D2D34AA6B /* PearlSizedTextView.h */; };
|
||||
93D3942C1B117EE4851AA7B6 /* UIView+Visible.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */; };
|
||||
93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */; };
|
||||
93D394B5036C882B33C71872 /* MPPasswordsSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */; };
|
||||
93D39508A6814612A5B3C226 /* MPMessageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399B36CDB2004D7C51391 /* MPMessageViewController.m */; };
|
||||
@@ -28,6 +30,7 @@
|
||||
93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */; };
|
||||
93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B381350802A194BF332 /* MPAvatarCell.m */; };
|
||||
93D39577FD8BB0945DB2F0A3 /* MPAlgorithmV3.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39FD9623E8D5571C0AEB3 /* MPAlgorithmV3.m */; };
|
||||
93D3959696396A91961C6148 /* UIView+AlphaScale.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D392D76C091DEA3319F11D /* UIView+AlphaScale.h */; };
|
||||
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D392C5A6572DB0EB5B82C8 /* mpw-types.c */; };
|
||||
93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; };
|
||||
93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */; };
|
||||
@@ -53,6 +56,7 @@
|
||||
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; };
|
||||
93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */; };
|
||||
93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */; };
|
||||
93D39BFB5F5F9337F6565DE3 /* UIView+Visible.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39B7B765546B1F1900CB7 /* UIView+Visible.h */; };
|
||||
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
|
||||
93D39D47FC623E91FC39D20C /* UICollectionView+PearlReloadFromArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3908DF8EABBD952065DC0 /* UICollectionView+PearlReloadFromArray.m */; };
|
||||
93D39D596A2E376D6F6F5DA1 /* MPCombinedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D393310223DDB35218467A /* MPCombinedViewController.m */; };
|
||||
@@ -67,6 +71,22 @@
|
||||
DA071BF4190187FE00179766 /* empty.png in Resources */ = {isa = PBXBuildFile; fileRef = DA071BF2190187FE00179766 /* empty.png */; };
|
||||
DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */; };
|
||||
DA0979171E9A81EE00F0BFE8 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979161E9A81EE00F0BFE8 /* libsodium.a */; };
|
||||
DA0CC5291EAB99BA009A8ED9 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5071EAB99BA009A8ED9 /* IASKAppSettingsViewController.m */; };
|
||||
DA0CC52A1EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5091EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m */; };
|
||||
DA0CC52B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC50B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m */; };
|
||||
DA0CC52C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC50D1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m */; };
|
||||
DA0CC52D1EAB99BA009A8ED9 /* IASKSettingsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5111EAB99BA009A8ED9 /* IASKSettingsReader.m */; };
|
||||
DA0CC52E1EAB99BA009A8ED9 /* IASKSettingsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5131EAB99BA009A8ED9 /* IASKSettingsStore.m */; };
|
||||
DA0CC52F1EAB99BA009A8ED9 /* IASKSettingsStoreFile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5151EAB99BA009A8ED9 /* IASKSettingsStoreFile.m */; };
|
||||
DA0CC5301EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5171EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m */; };
|
||||
DA0CC5311EAB99BA009A8ED9 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5191EAB99BA009A8ED9 /* IASKSpecifier.m */; };
|
||||
DA0CC5321EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC51C1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m */; };
|
||||
DA0CC5331EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC51E1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m */; };
|
||||
DA0CC5341EAB99BA009A8ED9 /* IASKSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5201EAB99BA009A8ED9 /* IASKSlider.m */; };
|
||||
DA0CC5351EAB99BA009A8ED9 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5221EAB99BA009A8ED9 /* IASKSwitch.m */; };
|
||||
DA0CC5361EAB99BA009A8ED9 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5241EAB99BA009A8ED9 /* IASKTextField.m */; };
|
||||
DA0CC5371EAB99BA009A8ED9 /* IASKTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5261EAB99BA009A8ED9 /* IASKTextView.m */; };
|
||||
DA0CC5381EAB99BA009A8ED9 /* IASKTextViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5281EAB99BA009A8ED9 /* IASKTextViewCell.m */; };
|
||||
DA24EBAE19DAD08900FF010B /* tip_basic_black_top.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38941711E29700CF925C /* tip_basic_black_top.png */; };
|
||||
DA24EBAF19DAD08C00FF010B /* tip_basic_black_top@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38951711E29700CF925C /* tip_basic_black_top@2x.png */; };
|
||||
DA24EBE819DAD6DE00FF010B /* Icon-320.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBE619DAD6DE00FF010B /* Icon-320.png */; };
|
||||
@@ -344,20 +364,6 @@
|
||||
DAF4EF50190A81E400023C90 /* NSManagedObject+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF4EF4E190A81E400023C90 /* NSManagedObject+Pearl.m */; };
|
||||
DAF4EF51190A81E400023C90 /* NSManagedObject+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF4EF4F190A81E400023C90 /* NSManagedObject+Pearl.h */; };
|
||||
DAFC5656172C573B00CB5CC5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||
DAFC5683172C57EC00CB5CC5 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5665172C57EC00CB5CC5 /* IASKAppSettingsViewController.m */; };
|
||||
DAFC5684172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5667172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m */; };
|
||||
DAFC5685172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5669172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m */; };
|
||||
DAFC5686172C57EC00CB5CC5 /* IASKSettingsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC566D172C57EC00CB5CC5 /* IASKSettingsReader.m */; };
|
||||
DAFC5687172C57EC00CB5CC5 /* IASKSettingsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC566F172C57EC00CB5CC5 /* IASKSettingsStore.m */; };
|
||||
DAFC5688172C57EC00CB5CC5 /* IASKSettingsStoreFile.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5671172C57EC00CB5CC5 /* IASKSettingsStoreFile.m */; };
|
||||
DAFC5689172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5673172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m */; };
|
||||
DAFC568A172C57EC00CB5CC5 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5675172C57EC00CB5CC5 /* IASKSpecifier.m */; };
|
||||
DAFC568B172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5678172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m */; };
|
||||
DAFC568C172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC567A172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m */; };
|
||||
DAFC568D172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC567C172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m */; };
|
||||
DAFC568E172C57EC00CB5CC5 /* IASKSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC567E172C57EC00CB5CC5 /* IASKSlider.m */; };
|
||||
DAFC568F172C57EC00CB5CC5 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */; };
|
||||
DAFC5690172C57EC00CB5CC5 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */; };
|
||||
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45D815039823003ABA7C /* NSObject+PearlExport.h */; };
|
||||
DAFE4A1415039824003ABA7C /* NSObject+PearlExport.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45D915039823003ABA7C /* NSObject+PearlExport.m */; };
|
||||
DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45DA15039823003ABA7C /* NSString+PearlNSArrayFormat.h */; };
|
||||
@@ -476,6 +482,7 @@
|
||||
93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsViewController.m; sourceTree = "<group>"; };
|
||||
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = "<group>"; };
|
||||
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-types.c"; sourceTree = "<group>"; };
|
||||
93D392D76C091DEA3319F11D /* UIView+AlphaScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+AlphaScale.h"; sourceTree = "<group>"; };
|
||||
93D393310223DDB35218467A /* MPCombinedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCombinedViewController.m; sourceTree = "<group>"; };
|
||||
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D393BB973253D4BAAC84AA /* PearlEMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlEMail.m; sourceTree = "<group>"; };
|
||||
@@ -483,8 +490,10 @@
|
||||
93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
|
||||
93D3942A356B639724157982 /* PearlOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlOverlay.h; sourceTree = "<group>"; };
|
||||
93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIResponder+PearlFirstResponder.h"; sourceTree = "<group>"; };
|
||||
93D39488AB33616661725929 /* UIView+AlphaScale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+AlphaScale.m"; sourceTree = "<group>"; };
|
||||
93D394D73F5BC92297CE8D7B /* MPAlgorithmV3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV3.h; sourceTree = "<group>"; };
|
||||
93D395105935859D71679931 /* MPOverlayViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayViewController.m; sourceTree = "<group>"; };
|
||||
93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Visible.m"; sourceTree = "<group>"; };
|
||||
93D3956915634581E737B38C /* PearlNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlNavigationController.m; sourceTree = "<group>"; };
|
||||
93D3957D76F71A652716EECC /* MPStoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStoreViewController.m; sourceTree = "<group>"; };
|
||||
93D3969393A3A46BD27D7078 /* mpw-algorithm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm.c"; sourceTree = "<group>"; };
|
||||
@@ -524,6 +533,7 @@
|
||||
93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUICollectionView.h; sourceTree = "<group>"; };
|
||||
93D39B381350802A194BF332 /* MPAvatarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAvatarCell.m; sourceTree = "<group>"; };
|
||||
93D39B455A71EC98C749E623 /* MPOverlayViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOverlayViewController.h; sourceTree = "<group>"; };
|
||||
93D39B7B765546B1F1900CB7 /* UIView+Visible.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Visible.h"; sourceTree = "<group>"; };
|
||||
93D39BAA71DE51B4D8A1286C /* MPCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCell.m; sourceTree = "<group>"; };
|
||||
93D39C41A27AA42D044D68AE /* NSString+MPMarkDown.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+MPMarkDown.m"; path = "iOS/NSString+MPMarkDown.m"; sourceTree = "<group>"; };
|
||||
93D39C426E03358384018E85 /* MPAnswersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAnswersViewController.m; sourceTree = "<group>"; };
|
||||
@@ -609,6 +619,54 @@
|
||||
DA0979131E9A81EE00F0BFE8 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
|
||||
DA0979141E9A81EE00F0BFE8 /* sodium.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sodium.h; sourceTree = "<group>"; };
|
||||
DA0979161E9A81EE00F0BFE8 /* libsodium.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsodium.a; sourceTree = "<group>"; };
|
||||
DA0CC4F61EAB99BA009A8ED9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4F71EAB99BA009A8ED9 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4F81EAB99BA009A8ED9 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4F91EAB99BA009A8ED9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4FA1EAB99BA009A8ED9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4FB1EAB99BA009A8ED9 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4FC1EAB99BA009A8ED9 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4FD1EAB99BA009A8ED9 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4FE1EAB99BA009A8ED9 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC4FF1EAB99BA009A8ED9 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/IASKLocalizable.strings"; sourceTree = "<group>"; };
|
||||
DA0CC5001EAB99BA009A8ED9 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC5011EAB99BA009A8ED9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC5021EAB99BA009A8ED9 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC5031EAB99BA009A8ED9 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC5041EAB99BA009A8ED9 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
|
||||
DA0CC5061EAB99BA009A8ED9 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = "<group>"; };
|
||||
DA0CC5071EAB99BA009A8ED9 /* IASKAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsViewController.m; sourceTree = "<group>"; };
|
||||
DA0CC5081EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsWebViewController.h; sourceTree = "<group>"; };
|
||||
DA0CC5091EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsWebViewController.m; sourceTree = "<group>"; };
|
||||
DA0CC50A1EAB99BA009A8ED9 /* IASKMultipleValueSelection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKMultipleValueSelection.h; sourceTree = "<group>"; };
|
||||
DA0CC50B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKMultipleValueSelection.m; sourceTree = "<group>"; };
|
||||
DA0CC50C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifierValuesViewController.h; sourceTree = "<group>"; };
|
||||
DA0CC50D1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifierValuesViewController.m; sourceTree = "<group>"; };
|
||||
DA0CC50E1EAB99BA009A8ED9 /* IASKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKViewController.h; sourceTree = "<group>"; };
|
||||
DA0CC5101EAB99BA009A8ED9 /* IASKSettingsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsReader.h; sourceTree = "<group>"; };
|
||||
DA0CC5111EAB99BA009A8ED9 /* IASKSettingsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsReader.m; sourceTree = "<group>"; };
|
||||
DA0CC5121EAB99BA009A8ED9 /* IASKSettingsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStore.h; sourceTree = "<group>"; };
|
||||
DA0CC5131EAB99BA009A8ED9 /* IASKSettingsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStore.m; sourceTree = "<group>"; };
|
||||
DA0CC5141EAB99BA009A8ED9 /* IASKSettingsStoreFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreFile.h; sourceTree = "<group>"; };
|
||||
DA0CC5151EAB99BA009A8ED9 /* IASKSettingsStoreFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreFile.m; sourceTree = "<group>"; };
|
||||
DA0CC5161EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreUserDefaults.h; sourceTree = "<group>"; };
|
||||
DA0CC5171EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreUserDefaults.m; sourceTree = "<group>"; };
|
||||
DA0CC5181EAB99BA009A8ED9 /* IASKSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifier.h; sourceTree = "<group>"; };
|
||||
DA0CC5191EAB99BA009A8ED9 /* IASKSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifier.m; sourceTree = "<group>"; };
|
||||
DA0CC51B1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSSliderSpecifierViewCell.h; sourceTree = "<group>"; };
|
||||
DA0CC51C1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSSliderSpecifierViewCell.m; sourceTree = "<group>"; };
|
||||
DA0CC51D1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTextFieldSpecifierViewCell.h; sourceTree = "<group>"; };
|
||||
DA0CC51E1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTextFieldSpecifierViewCell.m; sourceTree = "<group>"; };
|
||||
DA0CC51F1EAB99BA009A8ED9 /* IASKSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSlider.h; sourceTree = "<group>"; };
|
||||
DA0CC5201EAB99BA009A8ED9 /* IASKSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSlider.m; sourceTree = "<group>"; };
|
||||
DA0CC5211EAB99BA009A8ED9 /* IASKSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSwitch.h; sourceTree = "<group>"; };
|
||||
DA0CC5221EAB99BA009A8ED9 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = "<group>"; };
|
||||
DA0CC5231EAB99BA009A8ED9 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = "<group>"; };
|
||||
DA0CC5241EAB99BA009A8ED9 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = "<group>"; };
|
||||
DA0CC5251EAB99BA009A8ED9 /* IASKTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextView.h; sourceTree = "<group>"; };
|
||||
DA0CC5261EAB99BA009A8ED9 /* IASKTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextView.m; sourceTree = "<group>"; };
|
||||
DA0CC5271EAB99BA009A8ED9 /* IASKTextViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextViewCell.h; sourceTree = "<group>"; };
|
||||
DA0CC5281EAB99BA009A8ED9 /* IASKTextViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextViewCell.m; sourceTree = "<group>"; };
|
||||
DA24EBB219DAD4D000FF010B /* Icon-60.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60.png"; sourceTree = "<group>"; };
|
||||
DA24EBB319DAD4D000FF010B /* Icon-60@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBB419DAD4D000FF010B /* Icon-60@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@3x.png"; sourceTree = "<group>"; };
|
||||
@@ -1468,35 +1526,6 @@
|
||||
DAF4EF4E190A81E400023C90 /* NSManagedObject+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+Pearl.m"; sourceTree = "<group>"; };
|
||||
DAF4EF4F190A81E400023C90 /* NSManagedObject+Pearl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+Pearl.h"; sourceTree = "<group>"; };
|
||||
DAFC5655172C573B00CB5CC5 /* libInAppSettingsKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libInAppSettingsKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAFC5664172C57EC00CB5CC5 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = "<group>"; };
|
||||
DAFC5665172C57EC00CB5CC5 /* IASKAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsViewController.m; sourceTree = "<group>"; };
|
||||
DAFC5666172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsWebViewController.h; sourceTree = "<group>"; };
|
||||
DAFC5667172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsWebViewController.m; sourceTree = "<group>"; };
|
||||
DAFC5668172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifierValuesViewController.h; sourceTree = "<group>"; };
|
||||
DAFC5669172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifierValuesViewController.m; sourceTree = "<group>"; };
|
||||
DAFC566A172C57EC00CB5CC5 /* IASKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKViewController.h; sourceTree = "<group>"; };
|
||||
DAFC566C172C57EC00CB5CC5 /* IASKSettingsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsReader.h; sourceTree = "<group>"; };
|
||||
DAFC566D172C57EC00CB5CC5 /* IASKSettingsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsReader.m; sourceTree = "<group>"; };
|
||||
DAFC566E172C57EC00CB5CC5 /* IASKSettingsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStore.h; sourceTree = "<group>"; };
|
||||
DAFC566F172C57EC00CB5CC5 /* IASKSettingsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStore.m; sourceTree = "<group>"; };
|
||||
DAFC5670172C57EC00CB5CC5 /* IASKSettingsStoreFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreFile.h; sourceTree = "<group>"; };
|
||||
DAFC5671172C57EC00CB5CC5 /* IASKSettingsStoreFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreFile.m; sourceTree = "<group>"; };
|
||||
DAFC5672172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreUserDefaults.h; sourceTree = "<group>"; };
|
||||
DAFC5673172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreUserDefaults.m; sourceTree = "<group>"; };
|
||||
DAFC5674172C57EC00CB5CC5 /* IASKSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifier.h; sourceTree = "<group>"; };
|
||||
DAFC5675172C57EC00CB5CC5 /* IASKSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifier.m; sourceTree = "<group>"; };
|
||||
DAFC5677172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSSliderSpecifierViewCell.h; sourceTree = "<group>"; };
|
||||
DAFC5678172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSSliderSpecifierViewCell.m; sourceTree = "<group>"; };
|
||||
DAFC5679172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTextFieldSpecifierViewCell.h; sourceTree = "<group>"; };
|
||||
DAFC567A172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTextFieldSpecifierViewCell.m; sourceTree = "<group>"; };
|
||||
DAFC567B172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTitleValueSpecifierViewCell.h; sourceTree = "<group>"; };
|
||||
DAFC567C172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTitleValueSpecifierViewCell.m; sourceTree = "<group>"; };
|
||||
DAFC567D172C57EC00CB5CC5 /* IASKSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSlider.h; sourceTree = "<group>"; };
|
||||
DAFC567E172C57EC00CB5CC5 /* IASKSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSlider.m; sourceTree = "<group>"; };
|
||||
DAFC567F172C57EC00CB5CC5 /* IASKSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSwitch.h; sourceTree = "<group>"; };
|
||||
DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = "<group>"; };
|
||||
DAFC5681172C57EC00CB5CC5 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = "<group>"; };
|
||||
DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = "<group>"; };
|
||||
DAFE45D815039823003ABA7C /* NSObject+PearlExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PearlExport.h"; sourceTree = "<group>"; };
|
||||
DAFE45D915039823003ABA7C /* NSObject+PearlExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PearlExport.m"; sourceTree = "<group>"; };
|
||||
DAFE45DA15039823003ABA7C /* NSString+PearlNSArrayFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+PearlNSArrayFormat.h"; sourceTree = "<group>"; };
|
||||
@@ -1770,6 +1799,68 @@
|
||||
path = lib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA0CC4F41EAB99BA009A8ED9 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA0CC4F51EAB99BA009A8ED9 /* IASKLocalizable.strings */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA0CC5051EAB99BA009A8ED9 /* Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA0CC5061EAB99BA009A8ED9 /* IASKAppSettingsViewController.h */,
|
||||
DA0CC5071EAB99BA009A8ED9 /* IASKAppSettingsViewController.m */,
|
||||
DA0CC5081EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.h */,
|
||||
DA0CC5091EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m */,
|
||||
DA0CC50A1EAB99BA009A8ED9 /* IASKMultipleValueSelection.h */,
|
||||
DA0CC50B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m */,
|
||||
DA0CC50C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.h */,
|
||||
DA0CC50D1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m */,
|
||||
DA0CC50E1EAB99BA009A8ED9 /* IASKViewController.h */,
|
||||
);
|
||||
path = Controllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA0CC50F1EAB99BA009A8ED9 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA0CC5101EAB99BA009A8ED9 /* IASKSettingsReader.h */,
|
||||
DA0CC5111EAB99BA009A8ED9 /* IASKSettingsReader.m */,
|
||||
DA0CC5121EAB99BA009A8ED9 /* IASKSettingsStore.h */,
|
||||
DA0CC5131EAB99BA009A8ED9 /* IASKSettingsStore.m */,
|
||||
DA0CC5141EAB99BA009A8ED9 /* IASKSettingsStoreFile.h */,
|
||||
DA0CC5151EAB99BA009A8ED9 /* IASKSettingsStoreFile.m */,
|
||||
DA0CC5161EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.h */,
|
||||
DA0CC5171EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m */,
|
||||
DA0CC5181EAB99BA009A8ED9 /* IASKSpecifier.h */,
|
||||
DA0CC5191EAB99BA009A8ED9 /* IASKSpecifier.m */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA0CC51A1EAB99BA009A8ED9 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA0CC51B1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.h */,
|
||||
DA0CC51C1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m */,
|
||||
DA0CC51D1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.h */,
|
||||
DA0CC51E1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m */,
|
||||
DA0CC51F1EAB99BA009A8ED9 /* IASKSlider.h */,
|
||||
DA0CC5201EAB99BA009A8ED9 /* IASKSlider.m */,
|
||||
DA0CC5211EAB99BA009A8ED9 /* IASKSwitch.h */,
|
||||
DA0CC5221EAB99BA009A8ED9 /* IASKSwitch.m */,
|
||||
DA0CC5231EAB99BA009A8ED9 /* IASKTextField.h */,
|
||||
DA0CC5241EAB99BA009A8ED9 /* IASKTextField.m */,
|
||||
DA0CC5251EAB99BA009A8ED9 /* IASKTextView.h */,
|
||||
DA0CC5261EAB99BA009A8ED9 /* IASKTextView.m */,
|
||||
DA0CC5271EAB99BA009A8ED9 /* IASKTextViewCell.h */,
|
||||
DA0CC5281EAB99BA009A8ED9 /* IASKTextViewCell.m */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA24EBB019DAD4D000FF010B /* ios */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2865,64 +2956,15 @@
|
||||
DAFC5662172C57EC00CB5CC5 /* InAppSettingsKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAFC5663172C57EC00CB5CC5 /* Controllers */,
|
||||
DAFC566B172C57EC00CB5CC5 /* Models */,
|
||||
DAFC5676172C57EC00CB5CC5 /* Views */,
|
||||
DA0CC4F41EAB99BA009A8ED9 /* Resources */,
|
||||
DA0CC5051EAB99BA009A8ED9 /* Controllers */,
|
||||
DA0CC50F1EAB99BA009A8ED9 /* Models */,
|
||||
DA0CC51A1EAB99BA009A8ED9 /* Views */,
|
||||
);
|
||||
name = InAppSettingsKit;
|
||||
path = InAppSettingsKit/InAppSettingsKit;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAFC5663172C57EC00CB5CC5 /* Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAFC5664172C57EC00CB5CC5 /* IASKAppSettingsViewController.h */,
|
||||
DAFC5665172C57EC00CB5CC5 /* IASKAppSettingsViewController.m */,
|
||||
DAFC5666172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.h */,
|
||||
DAFC5667172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m */,
|
||||
DAFC5668172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.h */,
|
||||
DAFC5669172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m */,
|
||||
DAFC566A172C57EC00CB5CC5 /* IASKViewController.h */,
|
||||
);
|
||||
path = Controllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAFC566B172C57EC00CB5CC5 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAFC566C172C57EC00CB5CC5 /* IASKSettingsReader.h */,
|
||||
DAFC566D172C57EC00CB5CC5 /* IASKSettingsReader.m */,
|
||||
DAFC566E172C57EC00CB5CC5 /* IASKSettingsStore.h */,
|
||||
DAFC566F172C57EC00CB5CC5 /* IASKSettingsStore.m */,
|
||||
DAFC5670172C57EC00CB5CC5 /* IASKSettingsStoreFile.h */,
|
||||
DAFC5671172C57EC00CB5CC5 /* IASKSettingsStoreFile.m */,
|
||||
DAFC5672172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.h */,
|
||||
DAFC5673172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m */,
|
||||
DAFC5674172C57EC00CB5CC5 /* IASKSpecifier.h */,
|
||||
DAFC5675172C57EC00CB5CC5 /* IASKSpecifier.m */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAFC5676172C57EC00CB5CC5 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAFC5677172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.h */,
|
||||
DAFC5678172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m */,
|
||||
DAFC5679172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.h */,
|
||||
DAFC567A172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m */,
|
||||
DAFC567B172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.h */,
|
||||
DAFC567C172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m */,
|
||||
DAFC567D172C57EC00CB5CC5 /* IASKSlider.h */,
|
||||
DAFC567E172C57EC00CB5CC5 /* IASKSlider.m */,
|
||||
DAFC567F172C57EC00CB5CC5 /* IASKSwitch.h */,
|
||||
DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */,
|
||||
DAFC5681172C57EC00CB5CC5 /* IASKTextField.h */,
|
||||
DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAFE45D715039823003ABA7C /* Pearl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -3098,6 +3140,10 @@
|
||||
DAEFB01C19BCBD9E00525079 /* UIView+LayoutGone.m */,
|
||||
DAEC85B418E3DD9A007FC0DF /* UIView+Touches.h */,
|
||||
DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */,
|
||||
93D39488AB33616661725929 /* UIView+AlphaScale.m */,
|
||||
93D392D76C091DEA3319F11D /* UIView+AlphaScale.h */,
|
||||
93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */,
|
||||
93D39B7B765546B1F1900CB7 /* UIView+Visible.h */,
|
||||
);
|
||||
path = "Pearl-UIKit";
|
||||
sourceTree = "<group>";
|
||||
@@ -3206,6 +3252,8 @@
|
||||
93D39A53D76CA70786423458 /* UICollectionView+PearlReloadFromArray.h in Headers */,
|
||||
93D39AA4A0BE66A872CCC02E /* NSPersistentStore+PearlMigration.h in Headers */,
|
||||
93D399E4BC1E092A8C8B12AE /* NSOrderedSetOrArray.h in Headers */,
|
||||
93D3959696396A91961C6148 /* UIView+AlphaScale.h in Headers */,
|
||||
93D39BFB5F5F9337F6565DE3 /* UIView+Visible.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -3475,6 +3523,8 @@
|
||||
zh_HK,
|
||||
zh_TW,
|
||||
zu,
|
||||
Base,
|
||||
"pt-PT",
|
||||
);
|
||||
mainGroup = DA5BFA39147E415C00F98B1E;
|
||||
productRefGroup = DA5BFA45147E415C00F98B1E /* Products */;
|
||||
@@ -3912,6 +3962,8 @@
|
||||
93D39D47FC623E91FC39D20C /* UICollectionView+PearlReloadFromArray.m in Sources */,
|
||||
93D3928D629EA563F9EC4909 /* NSPersistentStore+PearlMigration.m in Sources */,
|
||||
93D392A33CCE85431E910C7B /* NSOrderedSetOrArray.m in Sources */,
|
||||
93D393AA69A1193401160418 /* UIView+AlphaScale.m in Sources */,
|
||||
93D3942C1B117EE4851AA7B6 /* UIView+Visible.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -3919,26 +3971,50 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAFC5683172C57EC00CB5CC5 /* IASKAppSettingsViewController.m in Sources */,
|
||||
DAFC5684172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m in Sources */,
|
||||
DAFC5685172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m in Sources */,
|
||||
DAFC5686172C57EC00CB5CC5 /* IASKSettingsReader.m in Sources */,
|
||||
DAFC5687172C57EC00CB5CC5 /* IASKSettingsStore.m in Sources */,
|
||||
DAFC5688172C57EC00CB5CC5 /* IASKSettingsStoreFile.m in Sources */,
|
||||
DAFC5689172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m in Sources */,
|
||||
DAFC568A172C57EC00CB5CC5 /* IASKSpecifier.m in Sources */,
|
||||
DAFC568B172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m in Sources */,
|
||||
DAFC568C172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m in Sources */,
|
||||
DAFC568D172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m in Sources */,
|
||||
DAFC568E172C57EC00CB5CC5 /* IASKSlider.m in Sources */,
|
||||
DAFC568F172C57EC00CB5CC5 /* IASKSwitch.m in Sources */,
|
||||
DAFC5690172C57EC00CB5CC5 /* IASKTextField.m in Sources */,
|
||||
DA0CC52B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m in Sources */,
|
||||
DA0CC5321EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m in Sources */,
|
||||
DA0CC52D1EAB99BA009A8ED9 /* IASKSettingsReader.m in Sources */,
|
||||
DA0CC52A1EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m in Sources */,
|
||||
DA0CC5291EAB99BA009A8ED9 /* IASKAppSettingsViewController.m in Sources */,
|
||||
DA0CC5381EAB99BA009A8ED9 /* IASKTextViewCell.m in Sources */,
|
||||
DA0CC5311EAB99BA009A8ED9 /* IASKSpecifier.m in Sources */,
|
||||
DA0CC5341EAB99BA009A8ED9 /* IASKSlider.m in Sources */,
|
||||
DA0CC5351EAB99BA009A8ED9 /* IASKSwitch.m in Sources */,
|
||||
DA0CC5331EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m in Sources */,
|
||||
DA0CC52E1EAB99BA009A8ED9 /* IASKSettingsStore.m in Sources */,
|
||||
DA0CC52C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m in Sources */,
|
||||
DA0CC5361EAB99BA009A8ED9 /* IASKTextField.m in Sources */,
|
||||
DA0CC5371EAB99BA009A8ED9 /* IASKTextView.m in Sources */,
|
||||
DA0CC52F1EAB99BA009A8ED9 /* IASKSettingsStoreFile.m in Sources */,
|
||||
DA0CC5301EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
DA0CC4F51EAB99BA009A8ED9 /* IASKLocalizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
DA0CC4F61EAB99BA009A8ED9 /* Base */,
|
||||
DA0CC4F71EAB99BA009A8ED9 /* de */,
|
||||
DA0CC4F81EAB99BA009A8ED9 /* el */,
|
||||
DA0CC4F91EAB99BA009A8ED9 /* en */,
|
||||
DA0CC4FA1EAB99BA009A8ED9 /* es */,
|
||||
DA0CC4FB1EAB99BA009A8ED9 /* fr */,
|
||||
DA0CC4FC1EAB99BA009A8ED9 /* it */,
|
||||
DA0CC4FD1EAB99BA009A8ED9 /* ja */,
|
||||
DA0CC4FE1EAB99BA009A8ED9 /* nl */,
|
||||
DA0CC4FF1EAB99BA009A8ED9 /* pt-PT */,
|
||||
DA0CC5001EAB99BA009A8ED9 /* pt */,
|
||||
DA0CC5011EAB99BA009A8ED9 /* ru */,
|
||||
DA0CC5021EAB99BA009A8ED9 /* sv */,
|
||||
DA0CC5031EAB99BA009A8ED9 /* th */,
|
||||
DA0CC5041EAB99BA009A8ED9 /* tr */,
|
||||
);
|
||||
name = IASKLocalizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DABD3BFA1711E2DC00CF925C /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
@@ -4005,7 +4081,6 @@
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"ADHOC=1",
|
||||
"$(inherited)",
|
||||
"NDEBUG=1",
|
||||
"NS_BLOCK_ASSERTIONS=1",
|
||||
@@ -4273,7 +4348,6 @@
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"ADHOC=1",
|
||||
"$(inherited)",
|
||||
"NDEBUG=1",
|
||||
"NS_BLOCK_ASSERTIONS=1",
|
||||
|
||||
@@ -2568,7 +2568,6 @@
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"ADHOC=1",
|
||||
"$(inherited)",
|
||||
"NDEBUG=1",
|
||||
"NS_BLOCK_ASSERTIONS=1",
|
||||
@@ -2838,7 +2837,6 @@
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"ADHOC=1",
|
||||
"$(inherited)",
|
||||
"NDEBUG=1",
|
||||
"NS_BLOCK_ASSERTIONS=1",
|
||||
|
||||
@@ -58,6 +58,7 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
||||
- (Class)classOfType:(MPSiteType)type;
|
||||
- (NSArray *)allTypes;
|
||||
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType;
|
||||
- (MPSiteType)defaultType;
|
||||
- (MPSiteType)nextType:(MPSiteType)type;
|
||||
- (MPSiteType)previousType:(MPSiteType)type;
|
||||
|
||||
|
||||
@@ -286,6 +286,11 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
return allTypes;
|
||||
}
|
||||
|
||||
- (MPSiteType)defaultType {
|
||||
|
||||
return MPSiteTypeGeneratedLong;
|
||||
}
|
||||
|
||||
- (MPSiteType)nextType:(MPSiteType)type {
|
||||
|
||||
switch (type) {
|
||||
@@ -309,9 +314,9 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
return MPSiteTypeStoredDevicePrivate;
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
return MPSiteTypeGeneratedPhrase;
|
||||
default:
|
||||
return MPSiteTypeGeneratedLong;
|
||||
}
|
||||
|
||||
return [self defaultType];
|
||||
}
|
||||
|
||||
- (MPSiteType)previousType:(MPSiteType)type {
|
||||
@@ -430,58 +435,38 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
|
||||
- (NSString *)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
dispatch_group_enter( group );
|
||||
__block NSString *result = nil;
|
||||
[self resolveLoginForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
result = result_;
|
||||
dispatch_group_leave( group );
|
||||
}];
|
||||
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return result;
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolveLoginForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
dispatch_group_enter( group );
|
||||
__block NSString *result = nil;
|
||||
[self resolvePasswordForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
result = result_;
|
||||
dispatch_group_leave( group );
|
||||
}];
|
||||
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return result;
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolvePasswordForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (NSString *)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
dispatch_group_enter( group );
|
||||
__block NSString *result = nil;
|
||||
[self resolveAnswerForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
result = result_;
|
||||
dispatch_group_leave( group );
|
||||
}];
|
||||
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return result;
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolveAnswerForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (NSString *)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)siteKey {
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
dispatch_group_enter( group );
|
||||
__block NSString *result = nil;
|
||||
[self resolveAnswerForQuestion:question usingKey:siteKey result:^(NSString *result_) {
|
||||
result = result_;
|
||||
dispatch_group_leave( group );
|
||||
}];
|
||||
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return result;
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolveAnswerForQuestion:question usingKey:siteKey result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey result:(void ( ^ )(NSString *result))resultBlock {
|
||||
@@ -498,10 +483,12 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
else
|
||||
algorithm = site.algorithm;
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
resultBlock( loginName || !loginGenerated? loginName:
|
||||
[algorithm generateLoginForSiteNamed:name usingKey:siteKey] );
|
||||
} );
|
||||
if (!loginGenerated || [loginName length])
|
||||
resultBlock( loginName );
|
||||
else
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generateLoginForSiteNamed:name usingKey:siteKey] );
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey result:(void ( ^ )(NSString *result))resultBlock {
|
||||
@@ -533,9 +520,8 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
else
|
||||
algorithm = site.algorithm;
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
NSString *result = [algorithm generatePasswordForSiteNamed:name ofType:type withCounter:counter usingKey:siteKey];
|
||||
resultBlock( result );
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generatePasswordForSiteNamed:name ofType:type withCounter:counter usingKey:siteKey] );
|
||||
} );
|
||||
break;
|
||||
}
|
||||
@@ -549,9 +535,8 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
|
||||
NSData *encryptedContent = ((MPStoredSiteEntity *)site).contentObject;
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
NSString *result = [self decryptContent:encryptedContent usingKey:siteKey];
|
||||
resultBlock( result );
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [self decryptContent:encryptedContent usingKey:siteKey] );
|
||||
} );
|
||||
break;
|
||||
}
|
||||
@@ -563,9 +548,8 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
NSDictionary *siteQuery = [self queryForDevicePrivateSiteNamed:site.name];
|
||||
NSData *encryptedContent = [PearlKeyChain dataOfItemForQuery:siteQuery];
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
NSString *result = [self decryptContent:encryptedContent usingKey:siteKey];
|
||||
resultBlock( result );
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [self decryptContent:encryptedContent usingKey:siteKey] );
|
||||
} );
|
||||
break;
|
||||
}
|
||||
@@ -584,9 +568,8 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
else
|
||||
algorithm = site.algorithm;
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
NSString *result = [algorithm generateAnswerForSiteNamed:name onQuestion:nil usingKey:siteKey];
|
||||
resultBlock( result );
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generateAnswerForSiteNamed:name onQuestion:nil usingKey:siteKey] );
|
||||
} );
|
||||
}
|
||||
|
||||
@@ -605,9 +588,8 @@ NSOperationQueue *_mpwQueue = nil;
|
||||
else if ([[MPAppDelegate_Shared get] isFeatureUnlocked:MPProductGenerateAnswers])
|
||||
algorithm = question.site.algorithm;
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
NSString *result = [algorithm generateAnswerForSiteNamed:name onQuestion:keyword usingKey:siteKey];
|
||||
resultBlock( result );
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generateAnswerForSiteNamed:name onQuestion:keyword usingKey:siteKey] );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
// Consumable product.
|
||||
return NO;
|
||||
|
||||
#if ADHOC || DEBUG
|
||||
#if DEBUG
|
||||
// All features are unlocked for beta / debug / mac versions.
|
||||
return YES;
|
||||
#else
|
||||
|
||||
@@ -72,14 +72,23 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
|
||||
MPKeyOrigin keyOrigin;
|
||||
NSDictionary *keyQuery = createKeyQuery( user, NO, &keyOrigin );
|
||||
NSData *keyData = [PearlKeyChain dataOfItemForQuery:keyQuery];
|
||||
if (!keyData) {
|
||||
id<MPAlgorithm> keyAlgorithm = user.algorithm;
|
||||
MPKey *key = [[MPKey alloc] initForFullName:user.name withKeyResolver:^NSData *(id<MPAlgorithm> algorithm) {
|
||||
return ![algorithm isEqual:keyAlgorithm]? nil:
|
||||
PearlMainQueueAwait( (id)^{
|
||||
return [PearlKeyChain dataOfItemForQuery:keyQuery];
|
||||
} );
|
||||
} keyOrigin:keyOrigin];
|
||||
|
||||
if ([key keyIDForAlgorithm:user.algorithm])
|
||||
inf( @"Found key in keychain for user: %@", user.userID );
|
||||
|
||||
else {
|
||||
inf( @"No key found in keychain for user: %@", user.userID );
|
||||
return nil;
|
||||
key = nil;
|
||||
}
|
||||
|
||||
inf( @"Found key in keychain for user: %@", user.userID );
|
||||
return [[MPKey alloc] initForFullName:user.name withKeyData:keyData forAlgorithm:user.algorithm keyOrigin:keyOrigin];
|
||||
return key;
|
||||
}
|
||||
|
||||
- (void)storeSavedKeyFor:(MPUserEntity *)user {
|
||||
@@ -230,28 +239,22 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
|
||||
NSString *content;
|
||||
while (!(content = [site.algorithm storedPasswordForSite:(MPStoredSiteEntity *)site usingKey:recoverKey])) {
|
||||
// Failed to decrypt site with the current recoveryKey. Ask user for a new one to use.
|
||||
__block NSString *masterPassword = nil;
|
||||
NSString *masterPassword = nil;
|
||||
|
||||
#ifdef PEARL_UIKIT
|
||||
dispatch_group_t recoverPasswordGroup = dispatch_group_create();
|
||||
dispatch_group_enter( recoverPasswordGroup );
|
||||
[PearlAlert showAlertWithTitle:@"Enter Old Master Password"
|
||||
message:PearlString( @"Your old master password is required to migrate the stored password for %@",
|
||||
site.name )
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
@try {
|
||||
masterPassword = PearlAwait( ^(void (^setResult)(id)) {
|
||||
[PearlAlert showAlertWithTitle:@"Enter Old Master Password"
|
||||
message:PearlString(
|
||||
@"Your old master password is required to migrate the stored password for %@",
|
||||
site.name )
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
// Don't Migrate
|
||||
return;
|
||||
|
||||
masterPassword = [alert_ textFieldAtIndex:0].text;
|
||||
}
|
||||
@finally {
|
||||
dispatch_group_leave( recoverPasswordGroup );
|
||||
}
|
||||
} cancelTitle:@"Don't Migrate" otherTitles:@"Migrate", nil];
|
||||
dispatch_group_wait( recoverPasswordGroup, DISPATCH_TIME_FOREVER );
|
||||
setResult( nil );
|
||||
else
|
||||
setResult( [alert_ textFieldAtIndex:0].text );
|
||||
} cancelTitle:@"Don't Migrate" otherTitles:@"Migrate", nil];
|
||||
} );
|
||||
#endif
|
||||
if (!masterPassword)
|
||||
// Don't Migrate
|
||||
|
||||
@@ -537,12 +537,13 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
|
||||
// Parse import data.
|
||||
inf( @"Importing sites." );
|
||||
__block MPUserEntity *user = nil;
|
||||
id<MPAlgorithm> importAlgorithm = nil;
|
||||
NSUInteger importFormat = 0;
|
||||
__block MPUserEntity *user = nil;
|
||||
NSUInteger importAvatar = NSNotFound;
|
||||
NSString *importBundleVersion = nil, *importUserName = nil;
|
||||
NSData *importKeyID = nil;
|
||||
NSString *importBundleVersion = nil, *importUserName = nil;
|
||||
id<MPAlgorithm> importAlgorithm = nil;
|
||||
MPSiteType importDefaultType = (MPSiteType)0;
|
||||
BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
|
||||
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
NSMutableSet *sitesToDelete = [NSMutableSet set];
|
||||
@@ -573,7 +574,15 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
|
||||
NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
|
||||
if ([headerName isEqualToString:@"User Name"]) {
|
||||
|
||||
if ([headerName isEqualToString:@"Format"]) {
|
||||
importFormat = (NSUInteger)[headerValue integerValue];
|
||||
if (importFormat >= [sitePatterns count]) {
|
||||
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
}
|
||||
if (([headerName isEqualToString:@"User Name"] || [headerName isEqualToString:@"Full Name"]) && !importUserName) {
|
||||
importUserName = headerValue;
|
||||
|
||||
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
@@ -591,21 +600,18 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
user = [users lastObject];
|
||||
dbg( @"Existing user? %@", [user debugDescription] );
|
||||
}
|
||||
if ([headerName isEqualToString:@"Avatar"])
|
||||
importAvatar = (NSUInteger)[headerValue integerValue];
|
||||
if ([headerName isEqualToString:@"Key ID"])
|
||||
importKeyID = [headerValue decodeHex];
|
||||
if ([headerName isEqualToString:@"Version"]) {
|
||||
importBundleVersion = headerValue;
|
||||
importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
|
||||
}
|
||||
if ([headerName isEqualToString:@"Format"]) {
|
||||
importFormat = (NSUInteger)[headerValue integerValue];
|
||||
if (importFormat >= [sitePatterns count]) {
|
||||
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
}
|
||||
if ([headerName isEqualToString:@"Avatar"])
|
||||
importAvatar = (NSUInteger)[headerValue integerValue];
|
||||
if ([headerName isEqualToString:@"Algorithm"])
|
||||
importAlgorithm = MPAlgorithmForVersion( (MPAlgorithmVersion)[headerValue integerValue] );
|
||||
if ([headerName isEqualToString:@"Default Type"])
|
||||
importDefaultType = (MPSiteType)[headerValue integerValue];
|
||||
if ([headerName isEqualToString:@"Passwords"]) {
|
||||
if ([headerValue isEqualToString:@"VISIBLE"])
|
||||
clearText = YES;
|
||||
@@ -709,6 +715,8 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
if (user) {
|
||||
if (importAvatar != NSNotFound)
|
||||
user.avatar = importAvatar;
|
||||
if (importDefaultType)
|
||||
user.defaultType = importDefaultType;
|
||||
dbg( @"Updating User: %@", [user debugDescription] );
|
||||
}
|
||||
else {
|
||||
@@ -716,6 +724,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
user.name = importUserName;
|
||||
user.algorithm = MPAlgorithmDefault;
|
||||
user.keyID = [userKey keyIDForAlgorithm:user.algorithm];
|
||||
user.defaultType = importDefaultType?: user.algorithm.defaultType;
|
||||
if (importAvatar != NSNotFound)
|
||||
user.avatar = importAvatar;
|
||||
dbg( @"Created User: %@", [user debugDescription] );
|
||||
@@ -785,16 +794,16 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
[export appendFormat:@"# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n"];
|
||||
[export appendFormat:@"# \n"];
|
||||
[export appendFormat:@"##\n"];
|
||||
[export appendFormat:@"# Format: 1\n"];
|
||||
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
|
||||
[export appendFormat:@"# User Name: %@\n", activeUser.name];
|
||||
[export appendFormat:@"# Full Name: %@\n", activeUser.name];
|
||||
[export appendFormat:@"# Avatar: %lu\n", (unsigned long)activeUser.avatar];
|
||||
[export appendFormat:@"# Key ID: %@\n", [activeUser.keyID encodeHex]];
|
||||
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
|
||||
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
||||
[export appendFormat:@"# Format: 1\n"];
|
||||
if (revealPasswords)
|
||||
[export appendFormat:@"# Passwords: VISIBLE\n"];
|
||||
else
|
||||
[export appendFormat:@"# Passwords: PROTECTED\n"];
|
||||
[export appendFormat:@"# Algorithm: %d\n", activeUser.algorithm.version];
|
||||
[export appendFormat:@"# Default Type: %d\n", activeUser.defaultType];
|
||||
[export appendFormat:@"# Passwords: %@\n", revealPasswords? @"VISIBLE": @"PROTECTED"];
|
||||
[export appendFormat:@"##\n"];
|
||||
[export appendFormat:@"#\n"];
|
||||
[export appendFormat:@"# Last Times Password Login\t Site\tSite\n"];
|
||||
|
||||
@@ -237,8 +237,8 @@
|
||||
// Invalid self.user.defaultType
|
||||
result = MPApplyFix( result, ^MPFixableResult {
|
||||
wrn( @"Invalid type for: %@ of %@, type: %ld. Will use %ld instead.",
|
||||
self.name, self.user.name, (long)self.type, (long)MPSiteTypeGeneratedLong );
|
||||
self.type = MPSiteTypeGeneratedLong;
|
||||
self.name, self.user.name, (long)self.type, (long)[self.algorithm defaultType] );
|
||||
self.type = [self.algorithm defaultType];
|
||||
return MPFixableResultProblemsFixed;
|
||||
} );
|
||||
if (![self isKindOfClass:[self.algorithm classOfType:self.type]])
|
||||
@@ -330,7 +330,7 @@
|
||||
|
||||
- (MPSiteType)defaultType {
|
||||
|
||||
return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
|
||||
return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: self.algorithm.defaultType;
|
||||
}
|
||||
|
||||
- (void)setDefaultType:(MPSiteType)aDefaultType {
|
||||
|
||||
@@ -28,12 +28,12 @@ typedef NS_ENUM( NSUInteger, MPKeyOrigin ) {
|
||||
|
||||
@interface MPKey : NSObject
|
||||
|
||||
@property(nonatomic, readonly) NSString *fullName;
|
||||
@property(nonatomic, readonly) MPKeyOrigin origin;
|
||||
@property(nonatomic, readonly, copy) NSString *fullName;
|
||||
|
||||
- (instancetype)initForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword;
|
||||
- (instancetype)initForFullName:(NSString *)fullName withKeyData:(NSData *)keyData
|
||||
forAlgorithm:(id<MPAlgorithm>)algorithm keyOrigin:(MPKeyOrigin)origin;
|
||||
- (instancetype)initForFullName:(NSString *)fullName withKeyResolver:(NSData *( ^ )(id<MPAlgorithm>))keyResolver
|
||||
keyOrigin:(MPKeyOrigin)origin;
|
||||
|
||||
- (NSData *)keyIDForAlgorithm:(id<MPAlgorithm>)algorithm;
|
||||
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm;
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
@interface MPKey()
|
||||
|
||||
@property(nonatomic) NSString *fullName;
|
||||
@property(nonatomic) MPKeyOrigin origin;
|
||||
@property(nonatomic) NSString *masterPassword;
|
||||
@property(nonatomic, copy) NSString *fullName;
|
||||
@property(nonatomic, copy) NSData *( ^keyResolver )(id<MPAlgorithm>);
|
||||
|
||||
@end
|
||||
|
||||
@@ -31,25 +31,22 @@
|
||||
|
||||
- (instancetype)initForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword {
|
||||
|
||||
return [self initForFullName:fullName withKeyResolver:^NSData *(id<MPAlgorithm> algorithm) {
|
||||
return [algorithm keyDataForFullName:self.fullName withMasterPassword:masterPassword];
|
||||
} keyOrigin:MPKeyOriginMasterPassword];
|
||||
}
|
||||
|
||||
- (instancetype)initForFullName:(NSString *)fullName withKeyResolver:(NSData *( ^ )(id<MPAlgorithm>))keyResolver
|
||||
keyOrigin:(MPKeyOrigin)origin {
|
||||
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_keyCache = [NSCache new];
|
||||
self.fullName = fullName;
|
||||
self.origin = MPKeyOriginMasterPassword;
|
||||
self.masterPassword = masterPassword;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initForFullName:(NSString *)fullName withKeyData:(NSData *)keyData
|
||||
forAlgorithm:(id<MPAlgorithm>)algorithm keyOrigin:(MPKeyOrigin)origin {
|
||||
|
||||
if (!(self = [self initForFullName:fullName withMasterPassword:nil]))
|
||||
return nil;
|
||||
|
||||
self.origin = origin;
|
||||
[_keyCache setObject:keyData forKey:algorithm];
|
||||
self.fullName = fullName;
|
||||
self.keyResolver = keyResolver;
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -61,15 +58,17 @@
|
||||
|
||||
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm {
|
||||
|
||||
NSData *keyData = [_keyCache objectForKey:algorithm];
|
||||
if (keyData)
|
||||
@synchronized (self) {
|
||||
NSData *keyData = [_keyCache objectForKey:algorithm];
|
||||
if (keyData)
|
||||
return keyData;
|
||||
|
||||
keyData = self.keyResolver( algorithm );
|
||||
if (keyData)
|
||||
[_keyCache setObject:keyData forKey:algorithm];
|
||||
|
||||
return keyData;
|
||||
|
||||
keyData = [algorithm keyDataForFullName:self.fullName withMasterPassword:self.masterPassword];
|
||||
if (keyData)
|
||||
[_keyCache setObject:keyData forKey:algorithm];
|
||||
|
||||
return keyData;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm trimmedLength:(NSUInteger)subKeyLength {
|
||||
@@ -80,7 +79,7 @@
|
||||
|
||||
- (BOOL)isEqualToKey:(MPKey *)key {
|
||||
|
||||
return [self.fullName isEqualToString:key.fullName] && [self.masterPassword isEqualToString:self.masterPassword];
|
||||
return [[self keyIDForAlgorithm:MPAlgorithmDefault] isEqualToData:[key keyIDForAlgorithm:MPAlgorithmDefault]];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
|
||||
[super windowDidLoad];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
|
||||
queue:nil usingBlock:^(NSNotification *note) {
|
||||
[MPMacAppDelegate get].initialWindowController = nil;
|
||||
}];
|
||||
PearlAddNotificationObserver( NSWindowWillCloseNotification, self.window, nil, ^(id host, NSNotification *note) {
|
||||
PearlRemoveNotificationObserversFrom( host );
|
||||
[MPMacAppDelegate get].initialWindowController = nil;
|
||||
} );
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
@@ -72,7 +72,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
NSString *crashlyticsAPIKey = [self crashlyticsAPIKey];
|
||||
if ([crashlyticsAPIKey length]) {
|
||||
inf(@"Initializing Crashlytics");
|
||||
#if defined (DEBUG) || defined (ADHOC)
|
||||
#if DEBUG
|
||||
[Crashlytics sharedInstance].debugMode = YES;
|
||||
#endif
|
||||
[[Crashlytics sharedInstance] setUserIdentifier:[PearlKeyChain deviceIdentifier]];
|
||||
|
||||
@@ -41,40 +41,38 @@
|
||||
[self replaceFonts:self.window.contentView];
|
||||
prof_rewind( @"replaceFonts" );
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
PearlAddNotificationObserver( NSWindowDidBecomeKeyNotification, self.window, [NSOperationQueue mainQueue],
|
||||
^(id host, NSNotification *note) {
|
||||
prof_new( @"didBecomeKey" );
|
||||
[self.window makeKeyAndOrderFront:nil];
|
||||
prof_rewind( @"fadeIn" );
|
||||
[self updateUser];
|
||||
prof_finish( @"updateUser" );
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
} );
|
||||
PearlAddNotificationObserver( NSWindowWillCloseNotification, self.window, [NSOperationQueue mainQueue],
|
||||
^(id host, NSNotification *note) {
|
||||
PearlRemoveNotificationObservers();
|
||||
|
||||
NSWindow *sheet = [self.window attachedSheet];
|
||||
if (sheet)
|
||||
[self.window endSheet:sheet];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillResignActiveNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
} );
|
||||
PearlAddNotificationObserver( NSApplicationWillResignActiveNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(id host, NSNotification *note) {
|
||||
[self.window close];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self updateUser];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self updateUser];
|
||||
}];
|
||||
} );
|
||||
PearlAddNotificationObserver( MPSignedInNotification, nil, [NSOperationQueue mainQueue], ^(id host, NSNotification *note) {
|
||||
[self updateUser];
|
||||
} );
|
||||
PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue], ^(id host, NSNotification *note) {
|
||||
[self updateUser];
|
||||
} );
|
||||
[self observeKeyPath:@"sitesController.selection" withBlock:^(id from, id to, NSKeyValueChange cause, id _self) {
|
||||
prof_new( @"sitesController.selection" );
|
||||
[_self updateSelection];
|
||||
prof_finish( @"updateSelection" );
|
||||
}];
|
||||
prof_rewind( @"observers" );
|
||||
|
||||
NSSearchFieldCell *siteFieldCell = (NSSearchFieldCell *)self.siteField.cell;
|
||||
NSSearchFieldCell *siteFieldCell = self.siteField.cell;
|
||||
siteFieldCell.searchButtonCell = nil;
|
||||
siteFieldCell.cancelButtonCell = nil;
|
||||
|
||||
|
||||
@@ -49,11 +49,10 @@ const long MPAvatarAdd = 10000;
|
||||
|
||||
[super awakeFromNib];
|
||||
|
||||
self.alpha = 0;
|
||||
self.visible = NO;
|
||||
|
||||
self.nameContainer.layer.cornerRadius = 5;
|
||||
|
||||
self.avatarImageView.hidden = NO;
|
||||
self.avatarImageView.layer.cornerRadius = self.avatarImageView.bounds.size.height / 2;
|
||||
self.avatarImageView.layer.masksToBounds = NO;
|
||||
self.avatarImageView.backgroundColor = [UIColor clearColor];
|
||||
@@ -211,7 +210,7 @@ const long MPAvatarAdd = 10000;
|
||||
[UIView animateWithDuration:animated? 0.5f: 0 delay:0
|
||||
options:UIViewAnimationOptionOverrideInheritedDuration | UIViewAnimationOptionBeginFromCurrentState
|
||||
animations:^{
|
||||
self.alpha = 1;
|
||||
self.visible = YES;
|
||||
|
||||
if (self.newUser) {
|
||||
if (self.mode == MPAvatarModeLowered)
|
||||
@@ -220,6 +219,10 @@ const long MPAvatarAdd = 10000;
|
||||
self.avatar = arc4random() % MPAvatarCount;
|
||||
}
|
||||
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.avatarImageView.alpha = self.visibility * 0.7f + 0.3f;
|
||||
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
|
||||
|
||||
switch (self.mode) {
|
||||
case MPAvatarModeLowered: {
|
||||
[self.avatarSizeConstraint updateConstant:
|
||||
@@ -227,10 +230,9 @@ const long MPAvatarAdd = 10000;
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.visible = YES;
|
||||
self.nameContainer.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.alpha = self.visibility * 0.7f + 0.3f;
|
||||
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
|
||||
self.avatarImageView.visible = YES;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedButInactive: {
|
||||
@@ -239,10 +241,9 @@ const long MPAvatarAdd = 10000;
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.visible = YES;
|
||||
self.nameContainer.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.alpha = 0;
|
||||
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
|
||||
self.avatarImageView.visible = NO;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndActive: {
|
||||
@@ -251,10 +252,9 @@ const long MPAvatarAdd = 10000;
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.visible = YES;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 1;
|
||||
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
|
||||
self.avatarImageView.visible = YES;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndHidden: {
|
||||
@@ -263,10 +263,9 @@ const long MPAvatarAdd = 10000;
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = 0;
|
||||
self.nameContainer.visible = NO;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 0;
|
||||
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
|
||||
self.avatarImageView.visible = NO;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndMinimized: {
|
||||
@@ -274,9 +273,9 @@ const long MPAvatarAdd = 10000;
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh + 2];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = 0;
|
||||
self.nameContainer.visible = NO;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 1;
|
||||
self.avatarImageView.visible = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -293,7 +292,7 @@ const long MPAvatarAdd = 10000;
|
||||
else
|
||||
self.avatarImageView.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.layer.cornerRadius = self.avatarImageView.bounds.size.height / 2;
|
||||
self.spinner.alpha = self.spinnerActive? 1: 0;
|
||||
self.spinner.visible = self.spinnerActive;
|
||||
|
||||
[self.contentView layoutIfNeeded];
|
||||
} completion:nil];
|
||||
|
||||
@@ -28,17 +28,16 @@
|
||||
|
||||
[super viewDidLoad];
|
||||
|
||||
_views = [NSArray arrayWithObjects:
|
||||
self.view0, self.view1, self.view2, self.view3, self.view4, self.view5, self.view6, self.view7, self.view8, self.view9, nil];
|
||||
_views = @[ self.view0, self.view1, self.view2, self.view3, self.view4, self.view5, self.view6, self.view7, self.view8, self.view9 ];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
self.viewProgress.hidden = NO;
|
||||
self.viewProgress.visible = YES;
|
||||
self.viewProgress.progress = 0;
|
||||
[_views makeObjectsPerformSelector:@selector( setAlpha: ) withObject:@0];
|
||||
[_views makeObjectsPerformSelector:@selector( setVisible: ) withObject:@NO];
|
||||
_nextView = 0;
|
||||
}
|
||||
|
||||
@@ -47,7 +46,7 @@
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
[_views[_nextView++] setAlpha:1];
|
||||
[_views[_nextView++] setVisible:YES];
|
||||
}];
|
||||
|
||||
_viewTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimer *timer) {
|
||||
@@ -56,11 +55,11 @@
|
||||
if (self.viewProgress.progress == 1)
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.viewProgress.progress = 0;
|
||||
[_views[_nextView++] setAlpha:1];
|
||||
[_views[_nextView++] setVisible:YES];
|
||||
|
||||
if (_nextView >= [_views count]) {
|
||||
[_viewTimer invalidate];
|
||||
self.viewProgress.hidden = YES;
|
||||
self.viewProgress.visible = NO;
|
||||
}
|
||||
}];
|
||||
} repeats:YES];
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
@property(weak, nonatomic) IBOutlet UISegmentedControl *typeControl;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *counterLabel;
|
||||
@property(weak, nonatomic) IBOutlet UIActivityIndicatorView *activity;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordLabel;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *passwordButton;
|
||||
@property(weak, nonatomic) IBOutlet UIView *tipContainer;
|
||||
|
||||
- (IBAction)controlChanged:(UIControl *)control;
|
||||
|
||||
@@ -81,21 +81,20 @@
|
||||
[self updatePassword];
|
||||
}
|
||||
|
||||
- (IBAction)copyPassword:(UITapGestureRecognizer *)recognizer {
|
||||
- (IBAction)copyPassword:(id)sender {
|
||||
|
||||
if (recognizer.state == UIGestureRecognizerStateEnded) {
|
||||
NSString *sitePassword = self.passwordLabel.text;
|
||||
if ([sitePassword length]) {
|
||||
[UIPasteboard generalPasteboard].string = sitePassword;
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.tipContainer.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished)
|
||||
PearlMainQueueAfter( 3, ^{
|
||||
self.tipContainer.alpha = 0;
|
||||
} );
|
||||
}];
|
||||
}
|
||||
NSString *sitePassword = [self.passwordButton titleForState:UIControlStateNormal];
|
||||
if ([sitePassword length]) {
|
||||
[UIPasteboard generalPasteboard].string = sitePassword;
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.tipContainer.visible = YES;
|
||||
} completion:^(BOOL finished) {
|
||||
PearlMainQueueAfter( 3, ^{
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.tipContainer.visible = NO;
|
||||
}];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +105,7 @@
|
||||
NSString *fullName = self.fullNameField.text;
|
||||
NSString *masterPassword = self.masterPasswordField.text;
|
||||
|
||||
self.passwordLabel.text = nil;
|
||||
[self.passwordButton setTitle:nil forState:UIControlStateNormal];
|
||||
[self.activity startAnimating];
|
||||
[_emergencyKeyQueue cancelAllOperations];
|
||||
[_emergencyKeyQueue addOperationWithBlock:^{
|
||||
@@ -128,7 +127,7 @@
|
||||
NSUInteger siteCounter = (NSUInteger)self.counterStepper.value;
|
||||
self.counterLabel.text = strf( @"%lu", (unsigned long)siteCounter );
|
||||
|
||||
self.passwordLabel.text = nil;
|
||||
[self.passwordButton setTitle:nil forState:UIControlStateNormal];
|
||||
[self.activity startAnimating];
|
||||
[_emergencyPasswordQueue cancelAllOperations];
|
||||
[_emergencyPasswordQueue addOperationWithBlock:^{
|
||||
@@ -138,7 +137,7 @@
|
||||
|
||||
PearlMainQueue( ^{
|
||||
[self.activity stopAnimating];
|
||||
self.passwordLabel.text = sitePassword;
|
||||
[self.passwordButton setTitle:sitePassword forState:UIControlStateNormal];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
UIButton *dismissButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[dismissButton addTarget:self action:@selector( dismissOverlay: ) forControlEvents:UIControlEventTouchUpInside];
|
||||
dismissButton.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5f];
|
||||
dismissButton.alpha = 0;
|
||||
dismissButton.visible = NO;
|
||||
dismissButton.frame = self.view.bounds;
|
||||
dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
_dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] =
|
||||
@@ -89,7 +89,7 @@
|
||||
[_dismissSegueByButton removeObjectForKey:dismissSegueKey];
|
||||
|
||||
[UIView animateWithDuration:0.1f animations:^{
|
||||
dismissButton.alpha = 0;
|
||||
dismissButton.visible = NO;
|
||||
} completion:^(BOOL finished) {
|
||||
[dismissButton removeFromSuperview];
|
||||
}];
|
||||
@@ -127,14 +127,14 @@
|
||||
|
||||
CGRectSetY( destinationViewController.view.frame, 100 );
|
||||
destinationViewController.view.transform = CGAffineTransformMakeScale( 1.2f, 1.2f );
|
||||
destinationViewController.view.alpha = 0;
|
||||
destinationViewController.view.visible = NO;
|
||||
|
||||
[UIView transitionWithView:containerViewController.view duration:0.3f
|
||||
options:UIViewAnimationOptionAllowAnimatedContent animations:^{
|
||||
destinationViewController.view.transform = CGAffineTransformIdentity;
|
||||
CGRectSetY( destinationViewController.view.frame, 0 );
|
||||
destinationViewController.view.alpha = 1;
|
||||
dismissButton.alpha = 1;
|
||||
destinationViewController.view.visible = YES;
|
||||
dismissButton.visible = YES;
|
||||
} completion:^(BOOL finished) {
|
||||
[destinationViewController didMoveToParentViewController:containerViewController];
|
||||
[containerViewController setNeedsStatusBarAppearanceUpdate];
|
||||
@@ -147,7 +147,7 @@
|
||||
options:UIViewAnimationOptionAllowAnimatedContent animations:^{
|
||||
CGRectSetY( sourceViewController.view.frame, 100 );
|
||||
sourceViewController.view.transform = CGAffineTransformMakeScale( 0.8f, 0.8f );
|
||||
sourceViewController.view.alpha = 0;
|
||||
sourceViewController.view.visible = NO;
|
||||
[containerViewController removeDismissButtonForViewController:sourceViewController];
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
@property(nonatomic, strong) IBOutlet UITextField *passwordField;
|
||||
@property(nonatomic, strong) IBOutlet UIView *loginNameContainer;
|
||||
@property(nonatomic, strong) IBOutlet UITextField *loginNameField;
|
||||
@property(nonatomic, strong) IBOutlet UILabel *loginNameGenerated;
|
||||
@property(nonatomic, strong) IBOutlet UILabel *strengthLabel;
|
||||
@property(nonatomic, strong) IBOutlet UILabel *counterLabel;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *counterButton;
|
||||
@@ -199,7 +200,7 @@
|
||||
atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
|
||||
|
||||
if (textField == self.loginNameField)
|
||||
self.loginNameButton.titleLabel.alpha = [self.loginNameField.text length] || self.loginNameField.enabled? 0: 1;
|
||||
self.loginNameButton.hidden = [self.loginNameField.attributedText length] || self.loginNameField.enabled;
|
||||
}
|
||||
|
||||
- (IBAction)textFieldDidChange:(UITextField *)textField {
|
||||
@@ -224,7 +225,7 @@
|
||||
|
||||
if (textField == self.passwordField || textField == self.loginNameField) {
|
||||
textField.enabled = NO;
|
||||
NSString *text = textField.text;
|
||||
NSString *text = [textField.attributedText string]?: textField.text;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPSiteEntity *site = [self siteInContext:context];
|
||||
@@ -235,10 +236,8 @@
|
||||
if ([site.algorithm savePassword:text toSite:site usingKey:[MPiOSAppDelegate get].key])
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Password Updated" dismissAfter:2];
|
||||
}
|
||||
else if (textField == self.loginNameField &&
|
||||
((site.loginGenerated && ![text length]) ||
|
||||
(!site.loginGenerated && ![text isEqualToString:site.loginName]))) {
|
||||
if (site.loginGenerated || !([site.loginName isEqualToString:text] || (!text && !site.loginName))) {
|
||||
else if (textField == self.loginNameField) {
|
||||
if (![text isEqualToString:[site.algorithm resolveLoginForSite:site usingKey:[MPiOSAppDelegate get].key]]) {
|
||||
site.loginGenerated = NO;
|
||||
site.loginName = text;
|
||||
|
||||
@@ -282,12 +281,12 @@
|
||||
|
||||
[self setMode:MPPasswordCellModePassword animated:YES];
|
||||
|
||||
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||
[PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic
|
||||
initSheet:^(UIActionSheet *sheet) {
|
||||
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||
for (NSNumber *typeNumber in [MPAlgorithmDefault allTypes]) {
|
||||
for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) {
|
||||
MPSiteType type = (MPSiteType)[typeNumber unsignedIntegerValue];
|
||||
NSString *typeName = [MPAlgorithmDefault nameOfType:type];
|
||||
NSString *typeName = [mainSite.algorithm nameOfType:type];
|
||||
if (type == mainSite.type)
|
||||
[sheet addButtonWithTitle:strf( @"● %@", typeName )];
|
||||
else
|
||||
@@ -297,7 +296,8 @@
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
MPSiteType type = (MPSiteType)[[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
|
||||
MPSiteType type = (MPSiteType)[[mainSite.algorithm allTypes][buttonIndex] unsignedIntegerValue]?:
|
||||
mainSite.user.defaultType?: mainSite.algorithm.defaultType;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPSiteEntity *site = [self siteInContext:context];
|
||||
@@ -507,10 +507,10 @@
|
||||
self.upgradeButton.gone = !mainSite.requiresExplicitMigration && ![[MPiOSConfig get].allowDowngrade boolValue];
|
||||
self.answersButton.gone = ![[MPiOSAppDelegate get] isFeatureUnlocked:MPProductGenerateAnswers];
|
||||
BOOL settingsMode = self.mode == MPPasswordCellModeSettings;
|
||||
self.loginNameContainer.alpha = settingsMode || mainSite.loginGenerated || [mainSite.loginName length]? 0.7f: 0;
|
||||
self.loginNameField.textColor = [UIColor colorWithHexString:mainSite.loginGenerated? @"5E636D": @"6D5E63"];
|
||||
self.modeButton.alpha = self.transientSite? 0: settingsMode? 0.5f: 0.1f;
|
||||
self.counterLabel.alpha = self.counterButton.alpha = mainSite.type & MPSiteTypeClassGenerated? 0.5f: 0;
|
||||
self.loginNameContainer.visible = settingsMode || mainSite.loginGenerated || [mainSite.loginName length];
|
||||
self.modeButton.visible = !self.transientSite;
|
||||
self.modeButton.alpha = settingsMode? 0.5f: 0.1f;
|
||||
self.counterLabel.visible = self.counterButton.visible = mainSite.type & MPSiteTypeClassGenerated;
|
||||
self.modeButton.selected = settingsMode;
|
||||
self.strengthLabel.gone = !settingsMode;
|
||||
self.modeScrollView.scrollEnabled = !self.transientSite;
|
||||
@@ -520,13 +520,21 @@
|
||||
[self.passwordField resignFirstResponder];
|
||||
}
|
||||
if ([[MPiOSAppDelegate get] isFeatureUnlocked:MPProductGenerateLogins])
|
||||
[self.loginNameButton setTitle:@"Tap to generate username or use pencil to save one" forState:UIControlStateNormal];
|
||||
[self.loginNameButton setTitle:@"Tap here to ⚙ generate username or the pencil to type one" forState:UIControlStateNormal];
|
||||
else
|
||||
[self.loginNameButton setTitle:@"Tap the pencil to save a username" forState:UIControlStateNormal];
|
||||
[self.loginNameButton setTitle:@"Tap the pencil to type a username" forState:UIControlStateNormal];
|
||||
|
||||
// Site Name
|
||||
[self updateSiteName:mainSite];
|
||||
|
||||
// Site Counter
|
||||
if ([mainSite isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||
self.counterLabel.text = strf( @"%lu", (unsigned long)((MPGeneratedSiteEntity *)mainSite).counter );
|
||||
|
||||
// Site Login Name
|
||||
self.loginNameField.enabled = self.passwordField.enabled = //
|
||||
[self.loginNameField isFirstResponder] || [self.passwordField isFirstResponder];
|
||||
|
||||
// Site Password
|
||||
self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
|
||||
self.passwordField.attributedPlaceholder = stra(
|
||||
@@ -534,14 +542,17 @@
|
||||
mainSite.type & MPSiteTypeClassGenerated? strl( @"..." ): @"", @{
|
||||
NSForegroundColorAttributeName: [UIColor whiteColor]
|
||||
} );
|
||||
|
||||
// Calculate Fields
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPSiteEntity *site = [self siteInContext:context];
|
||||
MPKey *key = [MPiOSAppDelegate get].key;
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
BOOL loginGenerated = site.loginGenerated;
|
||||
NSString *password = nil, *loginName = [site resolveLoginUsingKey:key];
|
||||
MPSiteType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPSiteTypeGeneratedLong;
|
||||
MPSiteType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPAlgorithmDefault.defaultType;
|
||||
if (self.transientSite && transientType & MPSiteTypeClassGenerated)
|
||||
password = [MPAlgorithmDefault generatePasswordForSiteNamed:self.transientSite ofType:transientType
|
||||
withCounter:1 usingKey:key];
|
||||
@@ -559,13 +570,15 @@
|
||||
BOOL requiresExplicitMigration = site.requiresExplicitMigration;
|
||||
|
||||
PearlMainQueue( ^{
|
||||
self.loginNameField.text = loginName;
|
||||
self.passwordField.text = password;
|
||||
self.strengthLabel.text = timeToCrackString;
|
||||
self.loginNameButton.titleLabel.alpha = [loginName length] || self.loginNameField.enabled? 0: 1;
|
||||
self.loginNameGenerated.hidden = !loginGenerated;
|
||||
self.loginNameField.attributedText =
|
||||
strarm( stra( loginName?: @"", self.siteNameLabel.textAttributes ), NSParagraphStyleAttributeName, nil );
|
||||
self.loginNameButton.hidden = [loginName length] || self.loginNameField.enabled;
|
||||
|
||||
if (![password length]) {
|
||||
self.indicatorView.alpha = 1;
|
||||
self.indicatorView.hidden = NO;
|
||||
[self.indicatorView removeFromSuperview];
|
||||
[self.modeScrollView addSubview:self.indicatorView];
|
||||
[self.contentView addConstraintsWithVisualFormat:@"V:[indicator][target]" options:NSLayoutFormatAlignAllCenterX
|
||||
@@ -575,7 +588,7 @@
|
||||
}];
|
||||
}
|
||||
else if (requiresExplicitMigration) {
|
||||
self.indicatorView.alpha = 1;
|
||||
self.indicatorView.hidden = NO;
|
||||
[self.indicatorView removeFromSuperview];
|
||||
[self.modeScrollView addSubview:self.indicatorView];
|
||||
[self.contentView addConstraintsWithVisualFormat:@"V:[indicator][target]" options:NSLayoutFormatAlignAllCenterX
|
||||
@@ -585,18 +598,10 @@
|
||||
}];
|
||||
}
|
||||
else
|
||||
self.indicatorView.alpha = 0;
|
||||
self.indicatorView.hidden = YES;
|
||||
} );
|
||||
}];
|
||||
|
||||
// Site Counter
|
||||
if ([mainSite isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||
self.counterLabel.text = strf( @"%lu", (unsigned long)((MPGeneratedSiteEntity *)mainSite).counter );
|
||||
|
||||
// Site Login Name
|
||||
self.loginNameField.enabled = self.passwordField.enabled = //
|
||||
[self.loginNameField isFirstResponder] || [self.passwordField isFirstResponder];
|
||||
|
||||
[self.contentView layoutIfNeeded];
|
||||
}];
|
||||
}
|
||||
@@ -616,8 +621,9 @@
|
||||
range:NSMakeRange( s, [self.fuzzyGroups[f] length] )];
|
||||
}
|
||||
|
||||
[attributedSiteName appendAttributedString:stra(
|
||||
strf( @" - %@", self.transientSite? @"Tap to create": [site.algorithm shortNameOfType:site.type] ), @{} )];
|
||||
if (self.transientSite)
|
||||
[attributedSiteName appendAttributedString:stra( @" – Tap to create", @{} )];
|
||||
|
||||
self.siteNameLabel.attributedText = attributedSiteName;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
NSUInteger _transientItem;
|
||||
NSCharacterSet *_siteNameAcceptableCharactersSet;
|
||||
NSArray *_fuzzyGroups;
|
||||
NSMutableArray *_passwordCollectionViewUpdatesBatch;
|
||||
}
|
||||
|
||||
#pragma mark - Life
|
||||
@@ -62,6 +63,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
_backgroundColor = self.passwordCollectionView.backgroundColor;
|
||||
_darkenedBackgroundColor = [_backgroundColor colorWithAlphaComponent:0.6f];
|
||||
_transientItem = NSNotFound;
|
||||
_passwordCollectionViewUpdatesBatch = [NSMutableArray arrayWithCapacity:4];
|
||||
|
||||
self.view.backgroundColor = [UIColor clearColor];
|
||||
[self.passwordCollectionView automaticallyAdjustInsetsForKeyboard];
|
||||
@@ -181,10 +183,13 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
|
||||
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
|
||||
|
||||
Weakify( self );
|
||||
|
||||
if (controller == _fetchedResultsController) {
|
||||
@try {
|
||||
[self.passwordCollectionView performBatchUpdates:^{
|
||||
[self fetchedItemsDidUpdate];
|
||||
@synchronized (_passwordCollectionViewUpdatesBatch) {
|
||||
[_passwordCollectionViewUpdatesBatch addObject:[^{
|
||||
Strongify( self );
|
||||
|
||||
switch (type) {
|
||||
case NSFetchedResultsChangeInsert:
|
||||
[self.passwordCollectionView insertItemsAtIndexPaths:@[ newIndexPath ]];
|
||||
@@ -193,18 +198,35 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
[self.passwordCollectionView deleteItemsAtIndexPaths:@[ indexPath ]];
|
||||
break;
|
||||
case NSFetchedResultsChangeMove:
|
||||
[self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
|
||||
if (![indexPath isEqual:newIndexPath])
|
||||
[self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
|
||||
break;
|
||||
case NSFetchedResultsChangeUpdate:
|
||||
[self.passwordCollectionView reloadItemsAtIndexPaths:@[ indexPath ]];
|
||||
break;
|
||||
}
|
||||
} completion:nil];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
wrn( @"While updating password cells: %@", [exception fullDescription] );
|
||||
[self.passwordCollectionView reloadData];
|
||||
} copy]];
|
||||
}
|
||||
|
||||
[controller.managedObjectContext performBlock:^{
|
||||
PearlMainQueueOperation( ^{
|
||||
@try {
|
||||
[self.passwordCollectionView performBatchUpdates:^{
|
||||
[self updateTransientItem];
|
||||
|
||||
@synchronized (_passwordCollectionViewUpdatesBatch) {
|
||||
for (VoidBlock block in _passwordCollectionViewUpdatesBatch)
|
||||
block();
|
||||
[_passwordCollectionViewUpdatesBatch removeAllObjects];
|
||||
}
|
||||
} completion:nil];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
wrn( @"While updating password cells: %@", [exception fullDescription] );
|
||||
[self.passwordCollectionView reloadData];
|
||||
}
|
||||
} );
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,37 +300,35 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
if (showTips & MPPasswordsBadNameTip)
|
||||
self.badNameTipContainer.alpha = 1;
|
||||
self.badNameTipContainer.visible = YES;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished)
|
||||
PearlMainQueueAfter( 5, ^{
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
if (showTips & MPPasswordsBadNameTip)
|
||||
self.badNameTipContainer.alpha = 0;
|
||||
}];
|
||||
} );
|
||||
PearlMainQueueAfter( 5, ^{
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
if (showTips & MPPasswordsBadNameTip)
|
||||
self.badNameTipContainer.visible = NO;
|
||||
}];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)fetchedItemsDidUpdate {
|
||||
- (void)updateTransientItem {
|
||||
|
||||
NSString *query = self.query;
|
||||
_showTransientItem = [query length] > 0;
|
||||
NSUInteger objects = ((id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[0]).numberOfObjects;
|
||||
if (_showTransientItem && objects == 1 &&
|
||||
[[[self.fetchedResultsController.fetchedObjects firstObject] name] isEqualToString:query])
|
||||
_showTransientItem = NO;
|
||||
if ([self.passwordCollectionView numberOfSections] > 0) {
|
||||
if (!_showTransientItem && _transientItem != NSNotFound)
|
||||
[self.passwordCollectionView deleteItemsAtIndexPaths:
|
||||
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
|
||||
else if (_showTransientItem && _transientItem == NSNotFound)
|
||||
[self.passwordCollectionView insertItemsAtIndexPaths:
|
||||
@[ [NSIndexPath indexPathForItem:objects inSection:0] ]];
|
||||
else if (_transientItem != NSNotFound)
|
||||
[self.passwordCollectionView reloadItemsAtIndexPaths:
|
||||
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
|
||||
_showTransientItem = [query length] > 0 && ![[[self.fetchedResultsController.sections[0] objects] filteredArrayUsingPredicate:
|
||||
[NSPredicate predicateWithBlock:^BOOL(MPSiteEntity *site, NSDictionary<NSString *, id> *bindings) {
|
||||
return [site.name isEqualToString:query];
|
||||
}]] count];
|
||||
if (!_showTransientItem && _transientItem != NSNotFound)
|
||||
[self.passwordCollectionView deleteItemsAtIndexPaths:
|
||||
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
|
||||
else if (_showTransientItem && _transientItem == NSNotFound) {
|
||||
NSUInteger objects = [self.fetchedResultsController.sections[0] numberOfObjects];
|
||||
[self.passwordCollectionView insertItemsAtIndexPaths:
|
||||
@[ [NSIndexPath indexPathForItem:objects inSection:0] ]];
|
||||
}
|
||||
else if (_transientItem != NSNotFound)
|
||||
[self.passwordCollectionView reloadItemsAtIndexPaths:
|
||||
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
|
||||
}
|
||||
|
||||
- (void)registerObservers {
|
||||
@@ -316,7 +336,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
PearlRemoveNotificationObservers();
|
||||
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPPasswordsViewController *self, NSNotification *note) {
|
||||
self.passwordSelectionContainer.alpha = 0;
|
||||
self.passwordSelectionContainer.visible = NO;
|
||||
} );
|
||||
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPPasswordsViewController *self, NSNotification *note) {
|
||||
@@ -325,7 +345,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPPasswordsViewController *self, NSNotification *note) {
|
||||
[UIView animateWithDuration:0.7f animations:^{
|
||||
self.passwordSelectionContainer.alpha = 1;
|
||||
self.passwordSelectionContainer.visible = YES;
|
||||
}];
|
||||
} );
|
||||
PearlAddNotificationObserver( MPSignedOutNotification, nil, nil,
|
||||
@@ -361,6 +381,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
if (mainContext)
|
||||
PearlAddNotificationObserver( NSManagedObjectContextDidSaveNotification, mainContext, nil,
|
||||
^(MPPasswordsViewController *self, NSNotification *note) {
|
||||
// TODO: either move this into the app delegate or remove the duplicate signOutAnimated: call from the app delegate.
|
||||
if (![[MPiOSAppDelegate get] activeUserInContext:note.object])
|
||||
[[MPiOSAppDelegate get] signOutAnimated:YES];
|
||||
} );
|
||||
@@ -421,7 +442,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
PearlMainQueue( ^{
|
||||
@try {
|
||||
[self.passwordCollectionView performBatchUpdates:^{
|
||||
[self fetchedItemsDidUpdate];
|
||||
[self updateTransientItem];
|
||||
|
||||
NSInteger fromSections = self.passwordCollectionView.numberOfSections;
|
||||
NSInteger toSections = [self numberOfSectionsInCollectionView:self.passwordCollectionView];
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
@implementation MPPopdownSegue {
|
||||
}
|
||||
|
||||
static char UnwindingObserverKey;
|
||||
|
||||
- (void)perform {
|
||||
|
||||
MPPasswordsViewController *passwordsVC;
|
||||
@@ -39,19 +37,20 @@ static char UnwindingObserverKey;
|
||||
[passwordsVC.popdownContainer addConstraintsWithVisualFormats:@[ @"H:|[popdownView]|", @"V:|[popdownView]|" ] options:0
|
||||
metrics:nil views:NSDictionaryOfVariableBindings( popdownView )];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
[[passwordsVC.popdownToTopConstraint updatePriority:1] layoutIfNeeded];
|
||||
} completion:^(BOOL finished) {
|
||||
[popdownVC didMoveToParentViewController:passwordsVC];
|
||||
[passwordsVC.popdownToTopConstraint layoutIfNeeded];
|
||||
|
||||
id<NSObject> observer = [[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:popdownVC
|
||||
destination:passwordsVC] perform];
|
||||
}];
|
||||
objc_setAssociatedObject( popdownVC, &UnwindingObserverKey, observer, OBJC_ASSOCIATION_RETAIN );
|
||||
}];
|
||||
[UIView animateWithDuration:0.6f delay:0 usingSpringWithDamping:0.75f initialSpringVelocity:1
|
||||
options:UIViewAnimationOptionCurveEaseOut animations:^{
|
||||
[[passwordsVC.popdownToTopConstraint updatePriority:1] layoutIfNeeded];
|
||||
} completion:^(BOOL finished) {
|
||||
[popdownVC didMoveToParentViewController:passwordsVC];
|
||||
|
||||
PearlAddNotificationObserverTo( popdownVC, MPSignedOutNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(id host, NSNotification *note) {
|
||||
[[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:popdownVC destination:passwordsVC]
|
||||
perform];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
else {
|
||||
popdownVC = self.sourceViewController;
|
||||
@@ -59,16 +58,16 @@ static char UnwindingObserverKey;
|
||||
passwordsVC = (id)passwordsVC.parentViewController);
|
||||
NSAssert( passwordsVC, @"Couldn't find passwords VC to pop back to." );
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:objc_getAssociatedObject( popdownVC, &UnwindingObserverKey )];
|
||||
objc_setAssociatedObject( popdownVC, &UnwindingObserverKey, nil, OBJC_ASSOCIATION_RETAIN );
|
||||
PearlRemoveNotificationObserversFrom( popdownVC );
|
||||
|
||||
[popdownVC willMoveToParentViewController:nil];
|
||||
[UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionOverrideInheritedDuration animations:^{
|
||||
[[passwordsVC.popdownToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
|
||||
} completion:^(BOOL finished) {
|
||||
[popdownVC.view removeFromSuperview];
|
||||
[popdownVC removeFromParentViewController];
|
||||
}];
|
||||
[UIView animateWithDuration:0.4f delay:0 options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionOverrideInheritedDuration
|
||||
animations:^{
|
||||
[[passwordsVC.popdownToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
|
||||
} completion:^(BOOL finished) {
|
||||
[popdownVC.view removeFromSuperview];
|
||||
[popdownVC removeFromParentViewController];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *exportCell;
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *checkInconsistencies;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView *avatarImage;
|
||||
@property(weak, nonatomic) IBOutlet UISegmentedControl *generatedTypeControl;
|
||||
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated1TypeControl;
|
||||
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated2TypeControl;
|
||||
@property(weak, nonatomic) IBOutlet UISegmentedControl *storedTypeControl;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *passwordTypeExample;
|
||||
|
||||
- (IBAction)previousAvatar:(id)sender;
|
||||
- (IBAction)nextAvatar:(id)sender;
|
||||
|
||||
@@ -55,12 +55,24 @@
|
||||
- (void)reload {
|
||||
|
||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForMainThread];
|
||||
self.generatedTypeControl.selectedSegmentIndex = [self generatedSegmentIndexForType:activeUser.defaultType];
|
||||
self.storedTypeControl.selectedSegmentIndex = [self storedSegmentIndexForType:activeUser.defaultType];
|
||||
self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)activeUser.avatar )];
|
||||
self.savePasswordSwitch.on = activeUser.saveKey;
|
||||
self.touchIDSwitch.on = activeUser.touchID;
|
||||
self.touchIDSwitch.enabled = self.savePasswordSwitch.on && [[MPiOSAppDelegate get] isFeatureUnlocked:MPProductTouchID];
|
||||
|
||||
MPSiteType defaultType = activeUser.defaultType;
|
||||
self.generated1TypeControl.selectedSegmentIndex = [self generated1SegmentIndexForType:defaultType];
|
||||
self.generated2TypeControl.selectedSegmentIndex = [self generated2SegmentIndexForType:defaultType];
|
||||
self.storedTypeControl.selectedSegmentIndex = [self storedSegmentIndexForType:defaultType];
|
||||
PearlNotMainQueue( ^{
|
||||
NSString *examplePassword = nil;
|
||||
if (defaultType & MPSiteTypeClassGenerated)
|
||||
examplePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:@"test" ofType:defaultType
|
||||
withCounter:1 usingKey:[MPiOSAppDelegate get].key];
|
||||
PearlMainQueue( ^{
|
||||
self.passwordTypeExample.text = [examplePassword length]? [NSString stringWithFormat:@"eg. %@", examplePassword]: nil;
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
@@ -88,14 +100,18 @@
|
||||
[self dismissPopup];
|
||||
[[MPiOSAppDelegate get] signOutAnimated:YES];
|
||||
}
|
||||
|
||||
if (cell == self.feedbackCell)
|
||||
[[MPiOSAppDelegate get] showFeedbackWithLogs:YES forVC:self];
|
||||
|
||||
if (cell == self.exportCell)
|
||||
[[MPiOSAppDelegate get] showExportForVC:self];
|
||||
|
||||
if (cell == self.showHelpCell) {
|
||||
MPPasswordsViewController *passwordsVC = [self dismissPopup];
|
||||
[passwordsVC performSegueWithIdentifier:@"guide" sender:self];
|
||||
}
|
||||
|
||||
if (cell == self.checkInconsistencies)
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
if ([[MPiOSAppDelegate get] findAndFixInconsistenciesSaveInContext:context] == MPFixableResultNoProblems)
|
||||
@@ -140,11 +156,13 @@
|
||||
} );
|
||||
}];
|
||||
|
||||
if (sender == self.generatedTypeControl || sender == self.storedTypeControl) {
|
||||
if (sender == self.generatedTypeControl)
|
||||
if (sender == self.generated1TypeControl || sender == self.generated2TypeControl || sender == self.storedTypeControl) {
|
||||
if (sender != self.generated1TypeControl)
|
||||
self.generated1TypeControl.selectedSegmentIndex = -1;
|
||||
if (sender != self.generated2TypeControl)
|
||||
self.generated2TypeControl.selectedSegmentIndex = -1;
|
||||
if (sender != self.storedTypeControl)
|
||||
self.storedTypeControl.selectedSegmentIndex = -1;
|
||||
else if (sender == self.storedTypeControl)
|
||||
self.generatedTypeControl.selectedSegmentIndex = -1;
|
||||
|
||||
MPSiteType defaultType = [self typeForSelectedSegment];
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
@@ -226,10 +244,17 @@
|
||||
|
||||
- (MPSiteType)typeForSelectedSegment {
|
||||
|
||||
NSInteger selectedGeneratedIndex = self.generatedTypeControl.selectedSegmentIndex;
|
||||
NSInteger selectedGenerated1Index = self.generated1TypeControl.selectedSegmentIndex;
|
||||
NSInteger selectedGenerated2Index = self.generated2TypeControl.selectedSegmentIndex;
|
||||
NSInteger selectedStoredIndex = self.storedTypeControl.selectedSegmentIndex;
|
||||
|
||||
switch (selectedGeneratedIndex) {
|
||||
switch (selectedGenerated1Index) {
|
||||
case 0:
|
||||
return MPSiteTypeGeneratedPhrase;
|
||||
case 1:
|
||||
return MPSiteTypeGeneratedName;
|
||||
default:
|
||||
switch (selectedGenerated2Index) {
|
||||
case 0:
|
||||
return MPSiteTypeGeneratedMaximum;
|
||||
case 1:
|
||||
@@ -250,13 +275,26 @@
|
||||
case 1:
|
||||
return MPSiteTypeStoredDevicePrivate;
|
||||
default:
|
||||
Throw( @"unsupported selected type index: generated=%ld, stored=%ld", (long)selectedGeneratedIndex,
|
||||
(long)selectedStoredIndex );
|
||||
Throw( @"unsupported selected type index: generated1=%ld, generated2=%ld, stored=%ld",
|
||||
(long)selectedGenerated1Index, (long)selectedGenerated2Index, (long)selectedStoredIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)generatedSegmentIndexForType:(MPSiteType)type {
|
||||
- (NSInteger)generated1SegmentIndexForType:(MPSiteType)type {
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
return 0;
|
||||
case MPSiteTypeGeneratedName:
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)generated2SegmentIndexForType:(MPSiteType)type {
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
|
||||
@@ -76,7 +76,7 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
[self reloadCellsHiding:self.allCellsBySection[0] showing:@[ self.loadingCell ]];
|
||||
[self.allCellsBySection[0] enumerateObjectsUsingBlock:^(MPStoreProductCell *cell, NSUInteger idx, BOOL *stop) {
|
||||
if ([cell isKindOfClass:[MPStoreProductCell class]]) {
|
||||
cell.purchasedIndicator.alpha = 0;
|
||||
cell.purchasedIndicator.visible = NO;
|
||||
[cell.activityIndicator stopAnimating];
|
||||
}
|
||||
}];
|
||||
@@ -313,7 +313,7 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
BOOL purchased = [[MPiOSAppDelegate get] isFeatureUnlocked:productIdentifier];
|
||||
NSInteger quantity = [self quantityForProductIdentifier:productIdentifier];
|
||||
cell.priceLabel.text = purchased? @"": [self.currencyFormatter stringFromNumber:@([product.price floatValue] * quantity)];
|
||||
cell.purchasedIndicator.alpha = purchased? 1: 0;
|
||||
cell.purchasedIndicator.visible = purchased;
|
||||
}
|
||||
|
||||
- (NSInteger)quantityForProductIdentifier:(NSString *)productIdentifier {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
inf( @"Type selection will appear" );
|
||||
self.recommendedTipContainer.alpha = 0;
|
||||
self.recommendedTipContainer.visible = NO;
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
@@ -42,15 +42,13 @@
|
||||
|
||||
if ([[MPiOSConfig get].firstRun boolValue])
|
||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||
self.recommendedTipContainer.alpha = 1;
|
||||
self.recommendedTipContainer.visible = YES;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished) {
|
||||
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.recommendedTipContainer.alpha = 0;
|
||||
}];
|
||||
} );
|
||||
}
|
||||
PearlMainQueueAfter( 5, ^{
|
||||
[UIView animateWithDuration:0.2f animations:^{
|
||||
self.recommendedTipContainer.visible = NO;
|
||||
}];
|
||||
} );
|
||||
}];
|
||||
|
||||
[super viewDidAppear:animated];
|
||||
@@ -89,11 +87,11 @@
|
||||
if ([selectedSite isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||
counter = ((MPGeneratedSiteEntity *)selectedSite).counter;
|
||||
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
||||
PearlNotMainQueue( ^{
|
||||
NSString *typeContent = [MPAlgorithmDefault generatePasswordForSiteNamed:name ofType:cellType
|
||||
withCounter:counter usingKey:[MPiOSAppDelegate get].key];
|
||||
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
PearlMainQueue( ^{
|
||||
[(UITextField *)[[tableView cellForRowAtIndexPath:indexPath] viewWithTag:2] setText:typeContent];
|
||||
} );
|
||||
} );
|
||||
|
||||
@@ -76,7 +76,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
|
||||
self.avatarCollectionView.allowsMultipleSelection = YES;
|
||||
[self.entryField addTarget:self action:@selector( textFieldEditingChanged: ) forControlEvents:UIControlEventEditingChanged];
|
||||
|
||||
self.preferencesTipContainer.alpha = 0;
|
||||
self.preferencesTipContainer.visible = NO;
|
||||
|
||||
[self setActive:YES animated:NO];
|
||||
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"tipped.thanks"])
|
||||
@@ -87,7 +87,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
|
||||
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
self.userSelectionContainer.alpha = 0;
|
||||
self.userSelectionContainer.visible = NO;
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
@@ -220,6 +220,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
|
||||
if (isNew) {
|
||||
user = [MPUserEntity insertNewObjectInContext:context];
|
||||
user.algorithm = MPAlgorithmDefault;
|
||||
user.defaultType = user.algorithm.defaultType;
|
||||
user.avatar = newUserAvatar;
|
||||
user.name = newUserName;
|
||||
}
|
||||
@@ -497,25 +498,25 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
if (showTips & MPUsersThanksTip)
|
||||
self.thanksTipContainer.alpha = 1;
|
||||
self.thanksTipContainer.visible = YES;
|
||||
if (showTips & MPUsersAvatarTip)
|
||||
self.avatarTipContainer.alpha = 1;
|
||||
self.avatarTipContainer.visible = YES;
|
||||
if (showTips & MPUsersMasterPasswordTip)
|
||||
self.entryTipContainer.alpha = 1;
|
||||
self.entryTipContainer.visible = YES;
|
||||
if (showTips & MPUsersPreferencesTip)
|
||||
self.preferencesTipContainer.alpha = 1;
|
||||
self.preferencesTipContainer.visible = YES;
|
||||
} completion:^(BOOL finished) {
|
||||
if (finished)
|
||||
PearlMainQueueAfter( 5, ^{
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
if (showTips & MPUsersThanksTip)
|
||||
self.thanksTipContainer.alpha = 0;
|
||||
self.thanksTipContainer.visible = NO;
|
||||
if (showTips & MPUsersAvatarTip)
|
||||
self.avatarTipContainer.alpha = 0;
|
||||
self.avatarTipContainer.visible = NO;
|
||||
if (showTips & MPUsersMasterPasswordTip)
|
||||
self.entryTipContainer.alpha = 0;
|
||||
self.entryTipContainer.visible = NO;
|
||||
if (showTips & MPUsersPreferencesTip)
|
||||
self.preferencesTipContainer.alpha = 0;
|
||||
self.preferencesTipContainer.visible = NO;
|
||||
}];
|
||||
} );
|
||||
}];
|
||||
@@ -538,14 +539,14 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
return;
|
||||
|
||||
[UIView animateWithDuration:timer? 0.5f: 0 animations:^{
|
||||
self.marqueeButton.alpha = 0;
|
||||
self.marqueeButton.visible = NO;
|
||||
} completion:^(BOOL finished) {
|
||||
if (!finished)
|
||||
return;
|
||||
|
||||
[self.marqueeButton setTitle:nextMarqueeString forState:UIControlStateNormal];
|
||||
[UIView animateWithDuration:timer? 0.5f: 0 animations:^{
|
||||
self.marqueeButton.alpha = 0.5f;
|
||||
self.marqueeButton.visible = YES;
|
||||
}];
|
||||
}];
|
||||
}
|
||||
@@ -588,8 +589,6 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
|
||||
- (void)updateAvatarVisibility {
|
||||
|
||||
self.previousAvatarButton.alpha = 0;
|
||||
self.nextAvatarButton.alpha = 0;
|
||||
for (NSIndexPath *indexPath in self.avatarCollectionView.indexPathsForVisibleItems) {
|
||||
MPAvatarCell *cell = (MPAvatarCell *)[self.avatarCollectionView cellForItemAtIndexPath:indexPath];
|
||||
[self updateVisibilityForAvatar:cell atIndexPath:indexPath animated:NO];
|
||||
@@ -633,10 +632,10 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
CGFloat visibility = MAX( 0, MIN( 1, 1 - ABS( current / (max / 2) - 1 ) ) );
|
||||
[cell setVisibility:visibility animated:animated];
|
||||
|
||||
if (cell.newUser) {
|
||||
self.previousAvatarButton.alpha = cell.mode == MPAvatarModeRaisedAndActive? visibility * 0.7f: 0;
|
||||
self.nextAvatarButton.alpha = cell.mode == MPAvatarModeRaisedAndActive? visibility * 0.7f: 0;
|
||||
}
|
||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||
self.nextAvatarButton.visible = self.previousAvatarButton.visible = cell.newUser && cell.mode == MPAvatarModeRaisedAndActive;
|
||||
self.nextAvatarButton.alpha = self.previousAvatarButton.alpha = visibility * 0.7f;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)afterUpdatesMainQueue:(void ( ^ )(void))block {
|
||||
@@ -657,7 +656,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
PearlRemoveNotificationObservers();
|
||||
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPUsersViewController *self, NSNotification *note) {
|
||||
self.userSelectionContainer.alpha = 0;
|
||||
self.userSelectionContainer.visible = NO;
|
||||
} );
|
||||
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPUsersViewController *self, NSNotification *note) {
|
||||
@@ -666,7 +665,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPUsersViewController *self, NSNotification *note) {
|
||||
[UIView animateWithDuration:0.5f animations:^{
|
||||
self.userSelectionContainer.alpha = 1;
|
||||
self.userSelectionContainer.visible = YES;
|
||||
}];
|
||||
} );
|
||||
PearlAddNotificationObserver( UIKeyboardWillShowNotification, nil, [NSOperationQueue mainQueue],
|
||||
@@ -678,7 +677,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
|
||||
NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.avatarCollectionView.alpha = mainContext? 1: 0;
|
||||
self.avatarCollectionView.visible = mainContext != nil;
|
||||
}];
|
||||
if (mainContext && self.storeLoadingActivity.isAnimating)
|
||||
[self.storeLoadingActivity stopAnimating];
|
||||
@@ -763,7 +762,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.userSelectionContainer.alpha = 1;
|
||||
self.userSelectionContainer.visible = YES;
|
||||
}];
|
||||
} );
|
||||
}
|
||||
@@ -828,8 +827,8 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
switch (activeUserState) {
|
||||
case MPActiveUserStateNone: {
|
||||
self.avatarCollectionView.scrollEnabled = YES;
|
||||
self.entryContainer.alpha = 0;
|
||||
self.footerContainer.alpha = 1;
|
||||
self.entryContainer.visible = NO;
|
||||
self.footerContainer.visible = YES;
|
||||
break;
|
||||
}
|
||||
case MPActiveUserStateLogin:
|
||||
@@ -837,15 +836,15 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
case MPActiveUserStateMasterPasswordChoice:
|
||||
case MPActiveUserStateMasterPasswordConfirmation: {
|
||||
self.avatarCollectionView.scrollEnabled = NO;
|
||||
self.entryContainer.alpha = 1;
|
||||
self.footerContainer.alpha = 1;
|
||||
self.entryContainer.visible = YES;
|
||||
self.footerContainer.visible = YES;
|
||||
requestFirstResponder = YES;
|
||||
break;
|
||||
}
|
||||
case MPActiveUserStateMinimized: {
|
||||
self.avatarCollectionView.scrollEnabled = NO;
|
||||
self.entryContainer.alpha = 0;
|
||||
self.footerContainer.alpha = 0;
|
||||
self.entryContainer.visible = NO;
|
||||
self.footerContainer.visible = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
self.webNavigationItem.title = self.initialURL.host;
|
||||
|
||||
self.webView.alpha = 0;
|
||||
self.webView.visible = NO;
|
||||
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:self.initialURL]];
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView {
|
||||
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
self.webView.alpha = 1;
|
||||
self.webView.visible = YES;
|
||||
}];
|
||||
|
||||
[self.webNavigationItem setLeftBarButtonItem:[webView canGoBack]? [[UIBarButtonItem alloc]
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "IASKSettingsReader.h"
|
||||
#import "MPStoreViewController.h"
|
||||
|
||||
@interface MPiOSAppDelegate()<UIDocumentInteractionControllerDelegate>
|
||||
@@ -53,7 +52,7 @@
|
||||
NSString *crashlyticsAPIKey = [self crashlyticsAPIKey];
|
||||
if ([crashlyticsAPIKey length]) {
|
||||
inf( @"Initializing Crashlytics" );
|
||||
#if defined (DEBUG) || defined (ADHOC)
|
||||
#if DEBUG
|
||||
[Crashlytics sharedInstance].debugMode = YES;
|
||||
#endif
|
||||
[[Crashlytics sharedInstance] setUserIdentifier:[PearlKeyChain deviceIdentifier]];
|
||||
@@ -89,18 +88,6 @@
|
||||
PearlAddNotificationObserver( NSUserDefaultsDidChangeNotification, nil, nil, ^(id self, NSNotification *note) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:nil];
|
||||
} );
|
||||
|
||||
#ifdef ADHOC
|
||||
[PearlAlert showAlertWithTitle:@"Welcome, tester!" message:
|
||||
@"Thank you for taking the time to test Master Password.\n\n"
|
||||
@"Please provide any feedback, however minor it may seem, via the Feedback action item accessible from the top right.\n\n"
|
||||
@"Contact me directly at:\n"
|
||||
@"lhunath@lyndir.com\n"
|
||||
@"Or report detailed issues at:\n"
|
||||
@"https://youtrack.lyndir.com\n"
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:nil
|
||||
cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
|
||||
#endif
|
||||
}
|
||||
@catch (id exception) {
|
||||
err( @"During Config Test: %@", exception );
|
||||
@@ -164,26 +151,24 @@
|
||||
return NO;
|
||||
|
||||
// Arbitrary URL to mpsites data.
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
|
||||
NSError *error;
|
||||
NSURLResponse *response;
|
||||
NSData *importedSitesData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url]
|
||||
returningResponse:&response error:&error];
|
||||
if (error)
|
||||
err( @"While reading imported sites from %@: %@", url, [error fullDescription] );
|
||||
if (!importedSitesData) {
|
||||
[PearlAlert showError:strf( @"Master Password couldn't read the import sites.\n\n%@", [error localizedDescription]?: error )];
|
||||
return;
|
||||
}
|
||||
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
|
||||
^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
|
||||
if (error)
|
||||
err( @"While reading imported sites from %@: %@", url, [error fullDescription] );
|
||||
if (!importedSitesData) {
|
||||
[PearlAlert showError:strf( @"Master Password couldn't read the import sites.\n\n%@",
|
||||
[error localizedDescription]?: error )];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
|
||||
if (!importedSitesString) {
|
||||
[PearlAlert showError:@"Master Password couldn't understand the import file."];
|
||||
return;
|
||||
}
|
||||
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
|
||||
if (!importedSitesString) {
|
||||
[PearlAlert showError:@"Master Password couldn't understand the import file."];
|
||||
return;
|
||||
}
|
||||
|
||||
[self importSites:importedSitesString];
|
||||
} );
|
||||
[self importSites:importedSitesString];
|
||||
}] resume];
|
||||
|
||||
return YES;
|
||||
}
|
||||
@@ -199,57 +184,33 @@
|
||||
|
||||
PearlOverlay *activityOverlay = [PearlOverlay showProgressOverlayWithTitle:@"Importing"];
|
||||
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
dispatch_group_t importPasswordGroup = dispatch_group_create();
|
||||
dispatch_group_enter( importPasswordGroup );
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[PearlAlert showAlertWithTitle:@"Import File's Master Password"
|
||||
message:strf( @"%@'s export was done using a different master password.\n"
|
||||
@"Enter that master password to unlock the exported data.", userName )
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
@try {
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
return;
|
||||
|
||||
masterPassword = [alert_ textFieldAtIndex:0].text;
|
||||
}
|
||||
@finally {
|
||||
dispatch_group_leave( importPasswordGroup );
|
||||
}
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
setResult( nil );
|
||||
else
|
||||
setResult( [alert_ textFieldAtIndex:0].text );
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock Import", nil];
|
||||
} );
|
||||
dispatch_group_wait( importPasswordGroup, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return masterPassword;
|
||||
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
dispatch_group_t userPasswordGroup = dispatch_group_create();
|
||||
dispatch_group_enter( userPasswordGroup );
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
return PearlAwait( (id)^(void (^setResult)(id)) {
|
||||
[PearlAlert showAlertWithTitle:strf( @"Master Password for\n%@", userName )
|
||||
message:strf( @"Imports %lu sites, overwriting %lu.",
|
||||
(unsigned long)importCount, (unsigned long)deleteCount )
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
@try {
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
return;
|
||||
|
||||
masterPassword = [alert_ textFieldAtIndex:0].text;
|
||||
}
|
||||
@finally {
|
||||
dispatch_group_leave( userPasswordGroup );
|
||||
}
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
setResult( nil );
|
||||
else
|
||||
setResult( [alert_ textFieldAtIndex:0].text );
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil];
|
||||
} );
|
||||
dispatch_group_wait( userPasswordGroup, DISPATCH_TIME_FOREVER );
|
||||
|
||||
return masterPassword;
|
||||
}];
|
||||
|
||||
switch (result) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,4 +5,4 @@ set -e
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
|
||||
rm -vfr lib/*/{.unpacked,.patched,src} lib/include
|
||||
rm -vfr {core,cli}{*.o,*.dSYM} mpw mpw-bench mpw-tests
|
||||
rm -vfr {core,cli,.}/{*.o,*.dSYM} mpw mpw-bench mpw-tests
|
||||
|
||||
@@ -11,19 +11,24 @@ mpwArchive=mpw-$commit.tar.gz
|
||||
[[ -e $mpwArchive ]] && echo >&2 "WARNING: $mpwArchive already exists. Will overwrite."
|
||||
read -n1 -p "Will prepare and release $mpwArchive. Press a key to continue or ^C to abort."
|
||||
|
||||
echo "Cleaning .."
|
||||
( git clean -ffdx . && cd core && git clean -ffdx . )
|
||||
|
||||
echo "Creating archive $mpwArchive .."
|
||||
git ls-files -z . | xargs -0 tar -Lcvzf "$mpwArchive"
|
||||
|
||||
echo "Creating archive signature $mpwArchive.sig .."
|
||||
gpg --detach-sign "$mpwArchive"
|
||||
|
||||
echo "Installing archive and signature in current site .."
|
||||
cd ../../public/site/current
|
||||
ln -sf "../../../platform-independent/cli-c/$mpwArchive"; [[ -e $_ ]]
|
||||
ln -sf "../../../platform-independent/cli-c/$mpwArchive.sig"; [[ -e $_ ]]
|
||||
mv "../../../platform-independent/cli-c/$mpwArchive" .; [[ -e $_ ]]
|
||||
mv "../../../platform-independent/cli-c/$mpwArchive.sig" .; [[ -e $_ ]]
|
||||
ln -sf "$mpwArchive" "masterpassword-cli.tar.gz"; [[ -e $_ ]]
|
||||
ln -sf "$mpwArchive.sig" "masterpassword-cli.tar.gz.sig"; [[ -e $_ ]]
|
||||
|
||||
echo
|
||||
echo "Done. Don't forget to publish the site."
|
||||
echo "package: $mpwArchive"
|
||||
echo "signature: $mpwArchive.sig"
|
||||
echo "Done. Ready to publish the site."
|
||||
echo " package: $mpwArchive"
|
||||
echo " signature: $mpwArchive.sig"
|
||||
echo " url: https://ssl.masterpasswordapp.com/$mpwArchive"
|
||||
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
../../../platform-independent/cli-c/mpw-2.1-cli1-0-g10f1001.tar.gz
|
||||
BIN
public/site/2013-05/mpw-2.1-cli1-0-g10f1001.tar.gz
Normal file
BIN
public/site/2013-05/mpw-2.1-cli1-0-g10f1001.tar.gz
Normal file
Binary file not shown.
@@ -1 +0,0 @@
|
||||
../../../platform-independent/cli-c/mpw-2.1-cli2-2-g82c96dd.tar.gz
|
||||
BIN
public/site/2013-05/mpw-2.1-cli2-2-g82c96dd.tar.gz
Normal file
BIN
public/site/2013-05/mpw-2.1-cli2-2-g82c96dd.tar.gz
Normal file
Binary file not shown.
@@ -1 +0,0 @@
|
||||
../../../platform-independent/cli-c/mpw-2.1-cli3-0-g438daf2.tar.gz
|
||||
BIN
public/site/2013-05/mpw-2.1-cli3-0-g438daf2.tar.gz
Normal file
BIN
public/site/2013-05/mpw-2.1-cli3-0-g438daf2.tar.gz
Normal file
Binary file not shown.
@@ -1 +0,0 @@
|
||||
../../../platform-independent/cli-c/mpw-2.1-cli4-0-gf6b2287.tar.gz
|
||||
BIN
public/site/2013-05/mpw-2.1-cli4-0-gf6b2287.tar.gz
Normal file
BIN
public/site/2013-05/mpw-2.1-cli4-0-gf6b2287.tar.gz
Normal file
Binary file not shown.
@@ -1 +0,0 @@
|
||||
../../../platform-independent/cli-c/mpw-2.5-cli-1-0-gb01e370f.tar.gz
|
||||
BIN
public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz
Normal file
BIN
public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz
Normal file
Binary file not shown.
@@ -1 +0,0 @@
|
||||
../../../platform-independent/cli-c/mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig
|
||||
BIN
public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig
Normal file
BIN
public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig
Normal file
Binary file not shown.
Reference in New Issue
Block a user