2
0

Cleanup, renaming restructuring, etc.

This commit is contained in:
Maarten Billemont 2017-05-07 18:36:01 -04:00
parent f86210f5da
commit fcbb93762a
62 changed files with 1599 additions and 1492 deletions

View File

@ -23,7 +23,7 @@
93D393DB5325820241BA90A7 /* PearlSizedTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39A4759186F6D2D34AA6B /* PearlSizedTextView.h */; }; 93D393DB5325820241BA90A7 /* PearlSizedTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39A4759186F6D2D34AA6B /* PearlSizedTextView.h */; };
93D3942C1B117EE4851AA7B6 /* UIView+Visible.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */; }; 93D3942C1B117EE4851AA7B6 /* UIView+Visible.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */; };
93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */; }; 93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */; };
93D394B5036C882B33C71872 /* MPPasswordsSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */; }; 93D394B5036C882B33C71872 /* MPSitesSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E7A12CC352B2825AA66 /* MPSitesSegue.m */; };
93D39508A6814612A5B3C226 /* MPMessageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399B36CDB2004D7C51391 /* MPMessageViewController.m */; }; 93D39508A6814612A5B3C226 /* MPMessageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399B36CDB2004D7C51391 /* MPMessageViewController.m */; };
93D39536EB550E811CCD04BC /* UIResponder+PearlFirstResponder.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */; }; 93D39536EB550E811CCD04BC /* UIResponder+PearlFirstResponder.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */; };
93D3954E96236384AFA00453 /* UIScrollView+PearlAdjustInsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */; }; 93D3954E96236384AFA00453 /* UIScrollView+PearlAdjustInsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */; };
@ -47,13 +47,13 @@
93D399E4BC1E092A8C8B12AE /* NSOrderedSetOrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39FBF8FCEB4C106272334 /* NSOrderedSetOrArray.h */; }; 93D399E4BC1E092A8C8B12AE /* NSOrderedSetOrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39FBF8FCEB4C106272334 /* NSOrderedSetOrArray.h */; };
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */; }; 93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */; };
93D39A53D76CA70786423458 /* UICollectionView+PearlReloadItems.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadItems.h */; }; 93D39A53D76CA70786423458 /* UICollectionView+PearlReloadItems.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadItems.h */; };
93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */; }; 93D39A5FF670957C0AF8298D /* MPSiteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPSiteCell.m */; };
93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */; }; 93D39A8EA1C49CE43B63F47B /* PearlUICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */; };
93D39AA4A0BE66A872CCC02E /* NSPersistentStore+PearlMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D397F4BAFFF7CF3F1B21A4 /* NSPersistentStore+PearlMigration.h */; }; 93D39AA4A0BE66A872CCC02E /* NSPersistentStore+PearlMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D397F4BAFFF7CF3F1B21A4 /* NSPersistentStore+PearlMigration.h */; };
93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */; }; 93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */; };
93D39B76DD5AB108BA8928E8 /* UIScrollView+PearlAdjustInsets.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */; }; 93D39B76DD5AB108BA8928E8 /* UIScrollView+PearlAdjustInsets.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */; };
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; }; 93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; };
93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */; }; 93D39B8F90F58A5D158DDBA3 /* MPSitesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPSitesViewController.m */; };
93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.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 */; }; 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 */; }; 93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
@ -476,14 +476,14 @@
93D390FADEB325D8D54A957D /* PearlOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlOverlay.m; sourceTree = "<group>"; }; 93D390FADEB325D8D54A957D /* PearlOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlOverlay.m; sourceTree = "<group>"; };
93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlAdjustInsets.m"; sourceTree = "<group>"; }; 93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlAdjustInsets.m"; sourceTree = "<group>"; };
93D39149A5F1F9B174D6D061 /* MPStoreViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStoreViewController.h; sourceTree = "<group>"; }; 93D39149A5F1F9B174D6D061 /* MPStoreViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStoreViewController.h; sourceTree = "<group>"; };
93D3914D7597F9A28DB9D85E /* MPPasswordsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsViewController.h; sourceTree = "<group>"; }; 93D3914D7597F9A28DB9D85E /* MPSitesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSitesViewController.h; sourceTree = "<group>"; };
93D39156E806BB78E04F78B9 /* PearlSizedTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSizedTextView.m; sourceTree = "<group>"; }; 93D39156E806BB78E04F78B9 /* PearlSizedTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSizedTextView.m; sourceTree = "<group>"; };
93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppSettingsViewController.m; sourceTree = "<group>"; }; 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppSettingsViewController.m; sourceTree = "<group>"; };
93D391943675426839501BB8 /* MPLogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogsViewController.h; sourceTree = "<group>"; }; 93D391943675426839501BB8 /* MPLogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogsViewController.h; sourceTree = "<group>"; };
93D391AA32F24290C424438E /* NSNotificationCenter+PearlEasyCleanup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+PearlEasyCleanup.h"; sourceTree = "<group>"; }; 93D391AA32F24290C424438E /* NSNotificationCenter+PearlEasyCleanup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+PearlEasyCleanup.h"; sourceTree = "<group>"; };
93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionView+PearlReloadItems.h"; sourceTree = "<group>"; }; 93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionView+PearlReloadItems.h"; sourceTree = "<group>"; };
93D3924D6F77E6BF41AC32D3 /* MPRootSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRootSegue.h; sourceTree = "<group>"; }; 93D3924D6F77E6BF41AC32D3 /* MPRootSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRootSegue.h; sourceTree = "<group>"; };
93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsViewController.m; sourceTree = "<group>"; }; 93D3924EE15017F8A12CB436 /* MPSitesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesViewController.m; sourceTree = "<group>"; };
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; 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>"; }; 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>"; }; 93D392D76C091DEA3319F11D /* UIView+AlphaScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+AlphaScale.h"; sourceTree = "<group>"; };
@ -517,7 +517,7 @@
93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = "<group>"; }; 93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = "<group>"; };
93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRootSegue.m; sourceTree = "<group>"; }; 93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRootSegue.m; sourceTree = "<group>"; };
93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = "<group>"; }; 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = "<group>"; };
93D39975CE5AEC99E3F086C7 /* MPPasswordCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordCell.h; sourceTree = "<group>"; }; 93D39975CE5AEC99E3F086C7 /* MPSiteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteCell.h; sourceTree = "<group>"; };
93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCoachmarkViewController.h; sourceTree = "<group>"; }; 93D3999693660C89A7465F4E /* MPCoachmarkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCoachmarkViewController.h; sourceTree = "<group>"; };
93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV2.m; sourceTree = "<group>"; }; 93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV2.m; sourceTree = "<group>"; };
93D399B36CDB2004D7C51391 /* MPMessageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMessageViewController.m; sourceTree = "<group>"; }; 93D399B36CDB2004D7C51391 /* MPMessageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMessageViewController.m; sourceTree = "<group>"; };
@ -541,7 +541,7 @@
93D39BAA71DE51B4D8A1286C /* MPCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCell.m; 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>"; }; 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>"; }; 93D39C426E03358384018E85 /* MPAnswersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAnswersViewController.m; sourceTree = "<group>"; };
93D39C44361BE57AF0B3071F /* MPPasswordsSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordsSegue.h; sourceTree = "<group>"; }; 93D39C44361BE57AF0B3071F /* MPSitesSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSitesSegue.h; sourceTree = "<group>"; };
93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppSettingsViewController.h; sourceTree = "<group>"; }; 93D39C86E984EC65DA5ACB1D /* MPAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppSettingsViewController.h; sourceTree = "<group>"; };
93D39CB0EABD2748740992D8 /* MPMessageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMessageViewController.h; sourceTree = "<group>"; }; 93D39CB0EABD2748740992D8 /* MPMessageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMessageViewController.h; sourceTree = "<group>"; };
93D39CC01630D0421205C4C4 /* MPNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNavigationController.m; sourceTree = "<group>"; }; 93D39CC01630D0421205C4C4 /* MPNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNavigationController.m; sourceTree = "<group>"; };
@ -554,8 +554,8 @@
93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; }; 93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; };
93D39DA27D768B53C8B1330C /* MPAvatarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAvatarCell.h; sourceTree = "<group>"; }; 93D39DA27D768B53C8B1330C /* MPAvatarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAvatarCell.h; sourceTree = "<group>"; };
93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlAdjustInsets.h"; sourceTree = "<group>"; }; 93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlAdjustInsets.h"; sourceTree = "<group>"; };
93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordCell.m; sourceTree = "<group>"; }; 93D39DEA995041A13DC9CAF7 /* MPSiteCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteCell.m; sourceTree = "<group>"; };
93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsSegue.m; sourceTree = "<group>"; }; 93D39E7A12CC352B2825AA66 /* MPSitesSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesSegue.m; sourceTree = "<group>"; };
93D39F556F2F142740A65E59 /* MPWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWebViewController.h; sourceTree = "<group>"; }; 93D39F556F2F142740A65E59 /* MPWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWebViewController.h; sourceTree = "<group>"; };
93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = "<group>"; }; 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = "<group>"; };
93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; }; 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; };
@ -2885,12 +2885,12 @@
93D39CC01630D0421205C4C4 /* MPNavigationController.m */, 93D39CC01630D0421205C4C4 /* MPNavigationController.m */,
93D39B455A71EC98C749E623 /* MPOverlayViewController.h */, 93D39B455A71EC98C749E623 /* MPOverlayViewController.h */,
93D395105935859D71679931 /* MPOverlayViewController.m */, 93D395105935859D71679931 /* MPOverlayViewController.m */,
93D39975CE5AEC99E3F086C7 /* MPPasswordCell.h */, 93D39975CE5AEC99E3F086C7 /* MPSiteCell.h */,
93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */, 93D39DEA995041A13DC9CAF7 /* MPSiteCell.m */,
93D39C44361BE57AF0B3071F /* MPPasswordsSegue.h */, 93D39C44361BE57AF0B3071F /* MPSitesSegue.h */,
93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */, 93D39E7A12CC352B2825AA66 /* MPSitesSegue.m */,
93D3914D7597F9A28DB9D85E /* MPPasswordsViewController.h */, 93D3914D7597F9A28DB9D85E /* MPSitesViewController.h */,
93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */, 93D3924EE15017F8A12CB436 /* MPSitesViewController.m */,
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */, 93D392876BE5C011DE73B43F /* MPPopdownSegue.h */,
93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */, 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */,
DABD3BEA1711E2DC00CF925C /* MPPreferencesViewController.h */, DABD3BEA1711E2DC00CF925C /* MPPreferencesViewController.h */,
@ -3859,14 +3859,14 @@
DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */, DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */,
93D39D596A2E376D6F6F5DA1 /* MPCombinedViewController.m in Sources */, 93D39D596A2E376D6F6F5DA1 /* MPCombinedViewController.m in Sources */,
93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */, 93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */,
93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */, 93D39B8F90F58A5D158DDBA3 /* MPSitesViewController.m in Sources */,
93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */, 93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */,
93D39392DEDA376F93C6C718 /* MPCell.m in Sources */, 93D39392DEDA376F93C6C718 /* MPCell.m in Sources */,
DA0CC58E1EB6B030009A8ED9 /* MPSiteQuestionEntity+CoreDataClass.m in Sources */, DA0CC58E1EB6B030009A8ED9 /* MPSiteQuestionEntity+CoreDataClass.m in Sources */,
93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */, 93D39A5FF670957C0AF8298D /* MPSiteCell.m in Sources */,
93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */, 93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */,
DA95B50F1C4776F00067F5EF /* NSMutableSet+Pearl.m in Sources */, DA95B50F1C4776F00067F5EF /* NSMutableSet+Pearl.m in Sources */,
93D394B5036C882B33C71872 /* MPPasswordsSegue.m in Sources */, 93D394B5036C882B33C71872 /* MPSitesSegue.m in Sources */,
DA0CC5911EB6B030009A8ED9 /* MPStoredSiteEntity+CoreDataProperties.m in Sources */, DA0CC5911EB6B030009A8ED9 /* MPStoredSiteEntity+CoreDataProperties.m in Sources */,
93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */, 93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */,
93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */, 93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */,

View File

@ -7,7 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */; }; 93D390C676DF52DA7E459F19 /* MPSitesWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D9D0061FF1159998F06 /* MPSitesWindow.m */; };
93D391E61DC23E128DA4446C /* NSView+Traversing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393EE88DE554BCCBC1C2D /* NSView+Traversing.h */; }; 93D391E61DC23E128DA4446C /* NSView+Traversing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393EE88DE554BCCBC1C2D /* NSView+Traversing.h */; };
93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */; }; 93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */; };
93D393A1646430FAAC73E7FE /* MPMacApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F83DD151985F2C7345A /* MPMacApplication.m */; }; 93D393A1646430FAAC73E7FE /* MPMacApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F83DD151985F2C7345A /* MPMacApplication.m */; };
@ -20,7 +20,7 @@
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; }; 93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
93D39C5789EFA607CF788082 /* MPSiteModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E73BF5CBF8E5B005CD3 /* MPSiteModel.m */; }; 93D39C5789EFA607CF788082 /* MPSiteModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E73BF5CBF8E5B005CD3 /* MPSiteModel.m */; };
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; }; 93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */; }; 93D39F833DEC1C89B2F795AC /* MPSitesWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A57A7823DE98A0FF83C /* MPSitesWindowController.m */; };
DA0933CC1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */; }; DA0933CC1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */; };
DA0933D01747B91B00DE1CEF /* appstore.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CF1747B91B00DE1CEF /* appstore.png */; }; DA0933D01747B91B00DE1CEF /* appstore.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CF1747B91B00DE1CEF /* appstore.png */; };
DA09745A1E99582900F0BFE8 /* mpw-tests-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA0974561E99582200F0BFE8 /* mpw-tests-util.c */; }; DA09745A1E99582900F0BFE8 /* mpw-tests-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA0974561E99582200F0BFE8 /* mpw-tests-util.c */; };
@ -36,6 +36,16 @@
DA16B345170661F2000A0EAB /* libPearl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC77CAD148291A600BCF976 /* libPearl.a */; }; DA16B345170661F2000A0EAB /* libPearl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC77CAD148291A600BCF976 /* libPearl.a */; };
DA2508F119511D3600AC23F1 /* MPPasswordWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */; }; DA2508F119511D3600AC23F1 /* MPPasswordWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */; };
DA250925195148E200AC23F1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; }; DA250925195148E200AC23F1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; };
DA26861D1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = DA26860A1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.m */; };
DA26861E1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = DA26860C1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.m */; };
DA26861F1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = DA26860E1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.m */; };
DA2686201EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2686101EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.m */; };
DA2686211EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2686121EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataClass.m */; };
DA2686221EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2686141EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.m */; };
DA2686231EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2686161EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.m */; };
DA2686241EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2686181EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.m */; };
DA2686251EBFD7A40001E37E /* MPUserEntity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = DA26861A1EBFD7A40001E37E /* MPUserEntity+CoreDataClass.m */; };
DA2686261EBFD7A40001E37E /* MPUserEntity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = DA26861C1EBFD7A40001E37E /* MPUserEntity+CoreDataProperties.m */; };
DA2C3D681BD9665B001137B3 /* PearlProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = DA2C3D661BD9665B001137B3 /* PearlProfiler.h */; }; DA2C3D681BD9665B001137B3 /* PearlProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = DA2C3D661BD9665B001137B3 /* PearlProfiler.h */; };
DA2C3D691BD9665B001137B3 /* PearlProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2C3D671BD9665B001137B3 /* PearlProfiler.m */; }; DA2C3D691BD9665B001137B3 /* PearlProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2C3D671BD9665B001137B3 /* PearlProfiler.m */; };
DA2CA4ED18D323D3007798F8 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2CA4E718D323D3007798F8 /* NSError+PearlFullDescription.m */; }; DA2CA4ED18D323D3007798F8 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2CA4E718D323D3007798F8 /* NSError+PearlFullDescription.m */; };
@ -48,11 +58,6 @@
DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */; }; DA30E9D215722EE500A68B4C /* Pearl-Crypto.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */; };
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9D515723E6900A68B4C /* PearlLazy.h */; }; DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */ = {isa = PBXBuildFile; fileRef = DA30E9D515723E6900A68B4C /* PearlLazy.h */; };
DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D615723E6900A68B4C /* PearlLazy.m */; }; DA30E9D815723E6900A68B4C /* PearlLazy.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30E9D615723E6900A68B4C /* PearlLazy.m */; };
DA32CFD919CF1C70004F3F0E /* MPGeneratedSiteEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA32CFD819CF1C70004F3F0E /* MPGeneratedSiteEntity.m */; };
DA32CFDC19CF1C70004F3F0E /* MPStoredSiteEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA32CFDB19CF1C70004F3F0E /* MPStoredSiteEntity.m */; };
DA32CFDF19CF1C70004F3F0E /* MPSiteEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA32CFDE19CF1C70004F3F0E /* MPSiteEntity.m */; };
DA32CFE219CF1C71004F3F0E /* MPSiteQuestionEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA32CFE119CF1C71004F3F0E /* MPSiteQuestionEntity.m */; };
DA32CFE519CF1C71004F3F0E /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA32CFE419CF1C71004F3F0E /* MPUserEntity.m */; };
DA3509FE15F101A500C14A8E /* PearlQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3509FC15F101A500C14A8E /* PearlQueue.h */; }; DA3509FE15F101A500C14A8E /* PearlQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3509FC15F101A500C14A8E /* PearlQueue.h */; };
DA3509FF15F101A500C14A8E /* PearlQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3509FD15F101A500C14A8E /* PearlQueue.m */; }; DA3509FF15F101A500C14A8E /* PearlQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3509FD15F101A500C14A8E /* PearlQueue.m */; };
DA3B844F190FC60900246EEA /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B844A190FC5A900246EEA /* Crashlytics.framework */; }; DA3B844F190FC60900246EEA /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA3B844A190FC5A900246EEA /* Crashlytics.framework */; };
@ -265,7 +270,7 @@
93D39240B5143E01F0B75E96 /* MPSiteModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteModel.h; sourceTree = "<group>"; }; 93D39240B5143E01F0B75E96 /* MPSiteModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteModel.h; sourceTree = "<group>"; };
93D392870DF659AFC1870521 /* NSView+Traversing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+Traversing.m"; sourceTree = "<group>"; }; 93D392870DF659AFC1870521 /* NSView+Traversing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+Traversing.m"; sourceTree = "<group>"; };
93D392A4F3DE0BD758B9B056 /* MPNoStateButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNoStateButton.h; sourceTree = "<group>"; }; 93D392A4F3DE0BD758B9B056 /* MPNoStateButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNoStateButton.h; sourceTree = "<group>"; };
93D392C3918763B3B72CF366 /* MPPasswordWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindowController.h; sourceTree = "<group>"; }; 93D392C3918763B3B72CF366 /* MPSitesWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSitesWindowController.h; sourceTree = "<group>"; };
93D392FD65A1DF0E8B2A45C6 /* MPGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPGradientView.h; sourceTree = "<group>"; }; 93D392FD65A1DF0E8B2A45C6 /* MPGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPGradientView.h; sourceTree = "<group>"; };
93D39368EF3CBFEF2AFCA15A /* MPInitialWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInitialWindowController.h; sourceTree = "<group>"; }; 93D39368EF3CBFEF2AFCA15A /* MPInitialWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInitialWindowController.h; sourceTree = "<group>"; };
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; }; 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
@ -274,13 +279,13 @@
93D39423D7BF4FD31FE6D27C /* MPSitesTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesTableView.m; sourceTree = "<group>"; }; 93D39423D7BF4FD31FE6D27C /* MPSitesTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesTableView.m; sourceTree = "<group>"; };
93D39538C4CEFF46DF379254 /* MPNoStateButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNoStateButton.m; sourceTree = "<group>"; }; 93D39538C4CEFF46DF379254 /* MPNoStateButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNoStateButton.m; sourceTree = "<group>"; };
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; }; 93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
93D3977484534E99F9BA579D /* MPPasswordWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindow.h; sourceTree = "<group>"; }; 93D3977484534E99F9BA579D /* MPSitesWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSitesWindow.h; sourceTree = "<group>"; };
93D39934FD8D5BFABA46F41C /* MPGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPGradientView.m; sourceTree = "<group>"; }; 93D39934FD8D5BFABA46F41C /* MPGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPGradientView.m; sourceTree = "<group>"; };
93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordWindowController.m; sourceTree = "<group>"; }; 93D39A57A7823DE98A0FF83C /* MPSitesWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesWindowController.m; sourceTree = "<group>"; };
93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = "<group>"; }; 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = "<group>"; };
93D39AC6360DDC16AEAA4119 /* MPSitesTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSitesTableView.h; sourceTree = "<group>"; }; 93D39AC6360DDC16AEAA4119 /* MPSitesTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSitesTableView.h; sourceTree = "<group>"; };
93D39D3CB30874147D9A9E1B /* MPInitialWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInitialWindowController.m; sourceTree = "<group>"; }; 93D39D3CB30874147D9A9E1B /* MPInitialWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInitialWindowController.m; sourceTree = "<group>"; };
93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordWindow.m; sourceTree = "<group>"; }; 93D39D9D0061FF1159998F06 /* MPSitesWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesWindow.m; sourceTree = "<group>"; };
93D39E73BF5CBF8E5B005CD3 /* MPSiteModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteModel.m; sourceTree = "<group>"; }; 93D39E73BF5CBF8E5B005CD3 /* MPSiteModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteModel.m; sourceTree = "<group>"; };
93D39F83DD151985F2C7345A /* MPMacApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMacApplication.m; sourceTree = "<group>"; }; 93D39F83DD151985F2C7345A /* MPMacApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMacApplication.m; sourceTree = "<group>"; };
DA0933C91747A56A00DE1CEF /* MPInitialWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPInitialWindow.xib; sourceTree = "<group>"; }; DA0933C91747A56A00DE1CEF /* MPInitialWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPInitialWindow.xib; sourceTree = "<group>"; };
@ -366,6 +371,26 @@
DA2508F919513C1400AC23F1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; DA2508F919513C1400AC23F1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
DA2508FA19513C1400AC23F1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; DA2508FA19513C1400AC23F1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
DA2508FB19513C1400AC23F1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; DA2508FB19513C1400AC23F1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
DA2686091EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPGeneratedSiteEntity+CoreDataClass.h"; sourceTree = "<group>"; };
DA26860A1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPGeneratedSiteEntity+CoreDataClass.m"; sourceTree = "<group>"; };
DA26860B1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPGeneratedSiteEntity+CoreDataProperties.h"; sourceTree = "<group>"; };
DA26860C1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPGeneratedSiteEntity+CoreDataProperties.m"; sourceTree = "<group>"; };
DA26860D1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPSiteEntity+CoreDataClass.h"; sourceTree = "<group>"; };
DA26860E1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteEntity+CoreDataClass.m"; sourceTree = "<group>"; };
DA26860F1EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPSiteEntity+CoreDataProperties.h"; sourceTree = "<group>"; };
DA2686101EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteEntity+CoreDataProperties.m"; sourceTree = "<group>"; };
DA2686111EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPSiteQuestionEntity+CoreDataClass.h"; sourceTree = "<group>"; };
DA2686121EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteQuestionEntity+CoreDataClass.m"; sourceTree = "<group>"; };
DA2686131EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPSiteQuestionEntity+CoreDataProperties.h"; sourceTree = "<group>"; };
DA2686141EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteQuestionEntity+CoreDataProperties.m"; sourceTree = "<group>"; };
DA2686151EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPStoredSiteEntity+CoreDataClass.h"; sourceTree = "<group>"; };
DA2686161EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPStoredSiteEntity+CoreDataClass.m"; sourceTree = "<group>"; };
DA2686171EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPStoredSiteEntity+CoreDataProperties.h"; sourceTree = "<group>"; };
DA2686181EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPStoredSiteEntity+CoreDataProperties.m"; sourceTree = "<group>"; };
DA2686191EBFD7A40001E37E /* MPUserEntity+CoreDataClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPUserEntity+CoreDataClass.h"; sourceTree = "<group>"; };
DA26861A1EBFD7A40001E37E /* MPUserEntity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPUserEntity+CoreDataClass.m"; sourceTree = "<group>"; };
DA26861B1EBFD7A40001E37E /* MPUserEntity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPUserEntity+CoreDataProperties.h"; sourceTree = "<group>"; };
DA26861C1EBFD7A40001E37E /* MPUserEntity+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPUserEntity+CoreDataProperties.m"; sourceTree = "<group>"; };
DA2C3D661BD9665B001137B3 /* PearlProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlProfiler.h; sourceTree = "<group>"; }; DA2C3D661BD9665B001137B3 /* PearlProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlProfiler.h; sourceTree = "<group>"; };
DA2C3D671BD9665B001137B3 /* PearlProfiler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlProfiler.m; sourceTree = "<group>"; }; DA2C3D671BD9665B001137B3 /* PearlProfiler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlProfiler.m; sourceTree = "<group>"; };
DA2CA4E718D323D3007798F8 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; }; DA2CA4E718D323D3007798F8 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; };
@ -378,16 +403,6 @@
DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-Crypto.m"; sourceTree = "<group>"; }; DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-Crypto.m"; sourceTree = "<group>"; };
DA30E9D515723E6900A68B4C /* PearlLazy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLazy.h; sourceTree = "<group>"; }; DA30E9D515723E6900A68B4C /* PearlLazy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLazy.h; sourceTree = "<group>"; };
DA30E9D615723E6900A68B4C /* PearlLazy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLazy.m; sourceTree = "<group>"; }; DA30E9D615723E6900A68B4C /* PearlLazy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLazy.m; sourceTree = "<group>"; };
DA32CFD719CF1C70004F3F0E /* MPGeneratedSiteEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPGeneratedSiteEntity.h; sourceTree = "<group>"; };
DA32CFD819CF1C70004F3F0E /* MPGeneratedSiteEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPGeneratedSiteEntity.m; sourceTree = "<group>"; };
DA32CFDA19CF1C70004F3F0E /* MPStoredSiteEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStoredSiteEntity.h; sourceTree = "<group>"; };
DA32CFDB19CF1C70004F3F0E /* MPStoredSiteEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStoredSiteEntity.m; sourceTree = "<group>"; };
DA32CFDD19CF1C70004F3F0E /* MPSiteEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteEntity.h; sourceTree = "<group>"; };
DA32CFDE19CF1C70004F3F0E /* MPSiteEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteEntity.m; sourceTree = "<group>"; };
DA32CFE019CF1C71004F3F0E /* MPSiteQuestionEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteQuestionEntity.h; sourceTree = "<group>"; };
DA32CFE119CF1C71004F3F0E /* MPSiteQuestionEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteQuestionEntity.m; sourceTree = "<group>"; };
DA32CFE319CF1C71004F3F0E /* MPUserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUserEntity.h; sourceTree = "<group>"; };
DA32CFE419CF1C71004F3F0E /* MPUserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUserEntity.m; sourceTree = "<group>"; };
DA3509FC15F101A500C14A8E /* PearlQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlQueue.h; sourceTree = "<group>"; }; DA3509FC15F101A500C14A8E /* PearlQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlQueue.h; sourceTree = "<group>"; };
DA3509FD15F101A500C14A8E /* PearlQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlQueue.m; sourceTree = "<group>"; }; DA3509FD15F101A500C14A8E /* PearlQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlQueue.m; sourceTree = "<group>"; };
DA3B844A190FC5A900246EEA /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = "<group>"; }; DA3B844A190FC5A900246EEA /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = "<group>"; };
@ -1244,20 +1259,30 @@
DA5E5CAC1724A667003798D8 /* MPEntities.m */, DA5E5CAC1724A667003798D8 /* MPEntities.m */,
DA3B8455190FC89700246EEA /* MPFixable.h */, DA3B8455190FC89700246EEA /* MPFixable.h */,
DA3B8454190FC89700246EEA /* MPFixable.m */, DA3B8454190FC89700246EEA /* MPFixable.m */,
DA32CFD719CF1C70004F3F0E /* MPGeneratedSiteEntity.h */, DA2686091EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.h */,
DA32CFD819CF1C70004F3F0E /* MPGeneratedSiteEntity.m */, DA26860A1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.m */,
DA26860B1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.h */,
DA26860C1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.m */,
DA5E5CAD1724A667003798D8 /* MPKey.h */, DA5E5CAD1724A667003798D8 /* MPKey.h */,
DA5E5CAE1724A667003798D8 /* MPKey.m */, DA5E5CAE1724A667003798D8 /* MPKey.m */,
DA32CFDD19CF1C70004F3F0E /* MPSiteEntity.h */, DA26860D1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.h */,
DA32CFDE19CF1C70004F3F0E /* MPSiteEntity.m */, DA26860E1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.m */,
DA32CFE019CF1C71004F3F0E /* MPSiteQuestionEntity.h */, DA26860F1EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.h */,
DA32CFE119CF1C71004F3F0E /* MPSiteQuestionEntity.m */, DA2686101EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.m */,
DA32CFDA19CF1C70004F3F0E /* MPStoredSiteEntity.h */, DA2686111EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataClass.h */,
DA32CFDB19CF1C70004F3F0E /* MPStoredSiteEntity.m */, DA2686121EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataClass.m */,
DA2686131EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.h */,
DA2686141EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.m */,
DA2686151EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.h */,
DA2686161EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.m */,
DA2686171EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.h */,
DA2686181EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.m */,
DA5E5CAF1724A667003798D8 /* MPTypes.h */, DA5E5CAF1724A667003798D8 /* MPTypes.h */,
DA4DAE931A7D8117003E5423 /* MPTypes.m */, DA4DAE931A7D8117003E5423 /* MPTypes.m */,
DA32CFE319CF1C71004F3F0E /* MPUserEntity.h */, DA2686191EBFD7A40001E37E /* MPUserEntity+CoreDataClass.h */,
DA32CFE419CF1C71004F3F0E /* MPUserEntity.m */, DA26861A1EBFD7A40001E37E /* MPUserEntity+CoreDataClass.m */,
DA26861B1EBFD7A40001E37E /* MPUserEntity+CoreDataProperties.h */,
DA26861C1EBFD7A40001E37E /* MPUserEntity+CoreDataProperties.m */,
); );
path = Source; path = Source;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1284,10 +1309,10 @@
DA5E5CB61724A667003798D8 /* MPMacConfig.m */, DA5E5CB61724A667003798D8 /* MPMacConfig.m */,
93D392A4F3DE0BD758B9B056 /* MPNoStateButton.h */, 93D392A4F3DE0BD758B9B056 /* MPNoStateButton.h */,
93D39538C4CEFF46DF379254 /* MPNoStateButton.m */, 93D39538C4CEFF46DF379254 /* MPNoStateButton.m */,
93D3977484534E99F9BA579D /* MPPasswordWindow.h */, 93D3977484534E99F9BA579D /* MPSitesWindow.h */,
93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */, 93D39D9D0061FF1159998F06 /* MPSitesWindow.m */,
93D392C3918763B3B72CF366 /* MPPasswordWindowController.h */, 93D392C3918763B3B72CF366 /* MPSitesWindowController.h */,
93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */, 93D39A57A7823DE98A0FF83C /* MPSitesWindowController.m */,
DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */, DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */,
93D39240B5143E01F0B75E96 /* MPSiteModel.h */, 93D39240B5143E01F0B75E96 /* MPSiteModel.h */,
93D39E73BF5CBF8E5B005CD3 /* MPSiteModel.m */, 93D39E73BF5CBF8E5B005CD3 /* MPSiteModel.m */,
@ -2382,35 +2407,40 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
DA2686251EBFD7A40001E37E /* MPUserEntity+CoreDataClass.m in Sources */,
DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */, DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */,
DA32CFE219CF1C71004F3F0E /* MPSiteQuestionEntity.m in Sources */, DA2686201EBFD7A40001E37E /* MPSiteEntity+CoreDataProperties.m in Sources */,
DA32CFE519CF1C71004F3F0E /* MPUserEntity.m in Sources */,
DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */, DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */,
DA26861E1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataProperties.m in Sources */,
DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */, DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */,
DA2686231EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.m in Sources */,
DA2686221EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.m in Sources */,
DACBFCDF1C59B22E007EF90F /* NSMutableSet+Pearl.m in Sources */, DACBFCDF1C59B22E007EF90F /* NSMutableSet+Pearl.m in Sources */,
DA2686241EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.m in Sources */,
DA6774311A4746AF004F356A /* mpw-util.c in Sources */, DA6774311A4746AF004F356A /* mpw-util.c in Sources */,
DA5E5CF91724A667003798D8 /* MPAppDelegate_Key.m in Sources */, DA5E5CF91724A667003798D8 /* MPAppDelegate_Key.m in Sources */,
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */, DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */,
DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */, DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */,
DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */, DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */,
DA26861F1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.m in Sources */,
DA3B8456190FC89700246EEA /* MPFixable.m in Sources */, DA3B8456190FC89700246EEA /* MPFixable.m in Sources */,
DA5E5D001724A667003798D8 /* MPEntities.m in Sources */, DA5E5D001724A667003798D8 /* MPEntities.m in Sources */,
DA2686261EBFD7A40001E37E /* MPUserEntity+CoreDataProperties.m in Sources */,
DA5E5D011724A667003798D8 /* MPKey.m in Sources */, DA5E5D011724A667003798D8 /* MPKey.m in Sources */,
DA32CFDC19CF1C70004F3F0E /* MPStoredSiteEntity.m in Sources */,
DA5E5D031724A667003798D8 /* MPMacAppDelegate.m in Sources */, DA5E5D031724A667003798D8 /* MPMacAppDelegate.m in Sources */,
DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */, DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */,
DA5E5D0C1724A667003798D8 /* main.m in Sources */, DA5E5D0C1724A667003798D8 /* main.m in Sources */,
93D39C5789EFA607CF788082 /* MPSiteModel.m in Sources */, 93D39C5789EFA607CF788082 /* MPSiteModel.m in Sources */,
DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */, DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */,
93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */, 93D39F833DEC1C89B2F795AC /* MPSitesWindowController.m in Sources */,
DA67742F1A4746AF004F356A /* mpw-types.c in Sources */, DA67742F1A4746AF004F356A /* mpw-types.c in Sources */,
DA32CFD919CF1C70004F3F0E /* MPGeneratedSiteEntity.m in Sources */, 93D390C676DF52DA7E459F19 /* MPSitesWindow.m in Sources */,
93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */, DA26861D1EBFD7A40001E37E /* MPGeneratedSiteEntity+CoreDataClass.m in Sources */,
93D39784E725A34D1EE3FB3B /* MPInitialWindowController.m in Sources */, 93D39784E725A34D1EE3FB3B /* MPInitialWindowController.m in Sources */,
DA32CFDF19CF1C70004F3F0E /* MPSiteEntity.m in Sources */,
93D394C4254EEB45FB335AFB /* MPSitesTableView.m in Sources */, 93D394C4254EEB45FB335AFB /* MPSitesTableView.m in Sources */,
DA6774291A4746AF004F356A /* mpw-algorithm.c in Sources */, DA6774291A4746AF004F356A /* mpw-algorithm.c in Sources */,
DA0CC5591EB6AE45009A8ED9 /* MasterPassword.xcdatamodeld in Sources */, DA0CC5591EB6AE45009A8ED9 /* MasterPassword.xcdatamodeld in Sources */,
DA2686211EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataClass.m in Sources */,
93D395E4830290EBB6E71F34 /* MPNoStateButton.m in Sources */, 93D395E4830290EBB6E71F34 /* MPNoStateButton.m in Sources */,
DA4DAE941A7D8117003E5423 /* MPAlgorithmV3.m in Sources */, DA4DAE941A7D8117003E5423 /* MPAlgorithmV3.m in Sources */,
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */, DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */,

View File

@ -29,7 +29,7 @@
#define CRACKING_PER_SECOND 2495000000UL #define CRACKING_PER_SECOND 2495000000UL
#define CRACKING_PRICE 350 #define CRACKING_PRICE 350
NSOperationQueue *_mpwQueue = nil; static NSOperationQueue *_mpwQueue = nil;
@implementation MPAlgorithmV0 @implementation MPAlgorithmV0

View File

@ -104,8 +104,10 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
if (![[MPAppDelegate_Shared get] canMakePayments]) { if (![[MPAppDelegate_Shared get] canMakePayments]) {
[PearlAlert showAlertWithTitle:@"Store Not Set Up" message: [PearlAlert showAlertWithTitle:@"App Store Not Set Up" message:
@"Try logging using the App Store or from Settings." @"Make sure your Apple ID is set under Settings -> iTunes & App Store, "
@"you have a payment method added to the account and purchases are"
@"not disabled under General -> Restrictions."
viewStyle:UIAlertViewStyleDefault initAlert:nil viewStyle:UIAlertViewStyleDefault initAlert:nil
tappedButtonBlock:nil cancelTitle:@"Thanks" otherTitles:nil]; tappedButtonBlock:nil cancelTitle:@"Thanks" otherTitles:nil];
return; return;

View File

@ -19,7 +19,9 @@
#import "MPEntities.h" #import "MPEntities.h"
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
@interface MPAppDelegate_Shared : PearlAppDelegate @interface MPAppDelegate_Shared : PearlAppDelegate
#else #else
@interface MPAppDelegate_Shared : NSObject<PearlConfigDelegate> @interface MPAppDelegate_Shared : NSObject<PearlConfigDelegate>

View File

@ -78,7 +78,6 @@
} }
- (void)handleCoordinatorError:(NSError *)error { - (void)handleCoordinatorError:(NSError *)error {
} }
@end @end

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPConfig.h // Master Password is free software: you can redistribute it and/or modify
// MasterPassword // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 02/01/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "Pearl.h" #import "Pearl.h"

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPConfig.m // Master Password is free software: you can redistribute it and/or modify
// MasterPassword // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 02/01/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPAppDelegate_Shared.h" #import "MPAppDelegate_Shared.h"

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPEntities.h // Master Password is free software: you can redistribute it and/or modify
// MasterPassword-iOS // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 31/05/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "MPSiteEntity+CoreDataClass.h" #import "MPSiteEntity+CoreDataClass.h"

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPEntities.m // Master Password is free software: you can redistribute it and/or modify
// MasterPassword-iOS // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 31/05/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPEntities.h" #import "MPEntities.h"
#import "MPAppDelegate_Shared.h" #import "MPAppDelegate_Shared.h"

View File

@ -1,20 +1,20 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// MPFixable.h // Master Password is free software: you can redistribute it and/or modify
// MPFixable // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by lhunath on 2014-04-26. // Master Password is distributed in the hope that it will be useful,
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>

View File

@ -1,20 +1,20 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// MPFixable.m // Master Password is free software: you can redistribute it and/or modify
// MPFixable // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by lhunath on 2014-04-26. // Master Password is distributed in the hope that it will be useful,
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPFixable.h" #import "MPFixable.h"

View File

@ -1,19 +1,20 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// MPKey // Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 16/07/12. // Master Password is distributed in the hope that it will be useful,
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "MPAlgorithm.h" #import "MPAlgorithm.h"

View File

@ -1,19 +1,20 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// MPKey // Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 16/07/12. // Master Password is distributed in the hope that it will be useful,
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPAlgorithm.h" #import "MPAlgorithm.h"
@ -22,12 +23,11 @@
@property(nonatomic) MPKeyOrigin origin; @property(nonatomic) MPKeyOrigin origin;
@property(nonatomic, copy) NSString *fullName; @property(nonatomic, copy) NSString *fullName;
@property(nonatomic, copy) NSData *( ^keyResolver )(id<MPAlgorithm>); @property(nonatomic, copy) NSData *( ^keyResolver )(id<MPAlgorithm>);
@property(nonatomic, strong) NSCache *keyCache;
@end @end
@implementation MPKey { @implementation MPKey;
NSCache *_keyCache;
};
- (instancetype)initForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword { - (instancetype)initForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword {
@ -42,7 +42,7 @@
if (!(self = [super init])) if (!(self = [super init]))
return nil; return nil;
_keyCache = [NSCache new]; self.keyCache = [NSCache new];
self.origin = origin; self.origin = origin;
self.fullName = fullName; self.fullName = fullName;
@ -59,13 +59,13 @@
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm { - (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm {
@synchronized (self) { @synchronized (self) {
NSData *keyData = [_keyCache objectForKey:algorithm]; NSData *keyData = [self.keyCache objectForKey:algorithm];
if (keyData) if (keyData)
return keyData; return keyData;
keyData = self.keyResolver( algorithm ); keyData = self.keyResolver( algorithm );
if (keyData) if (keyData)
[_keyCache setObject:keyData forKey:algorithm]; [self.keyCache setObject:keyData forKey:algorithm];
return keyData; return keyData;
} }

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPTypes.h // Master Password is free software: you can redistribute it and/or modify
// MasterPassword // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 02/01/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Crashlytics/Crashlytics.h> #import <Crashlytics/Crashlytics.h>
#import <Crashlytics/Answers.h> #import <Crashlytics/Answers.h>
@ -37,7 +47,7 @@ __END_DECLS
} \ } \
}) })
#else #else
#define MPError(error_, ...) ({ \ #define MPError(error_, message, ...) ({ \
err( message @"%@%@", ##__VA_ARGS__, error_? @"\n": @"", [error_ fullDescription]?: @"" ); \ err( message @"%@%@", ##__VA_ARGS__, error_? @"\n": @"", [error_ fullDescription]?: @"" ); \
}) })
#endif #endif

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPTypes.c // Master Password is free software: you can redistribute it and/or modify
// MasterPassword // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 02/01/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPTypes.h" #import "MPTypes.h"

View File

@ -18,9 +18,13 @@
#import "MPGradientView.h" #import "MPGradientView.h"
@implementation MPGradientView { @interface MPGradientView()
NSGradient *gradient;
} @property(nonatomic, strong) NSGradient *gradient;
@end
@implementation MPGradientView
- (id)initWithFrame:(NSRect)frame { - (id)initWithFrame:(NSRect)frame {
@ -51,28 +55,28 @@
- (void)setStartingColor:(NSColor *)startingColor { - (void)setStartingColor:(NSColor *)startingColor {
_startingColor = startingColor; _startingColor = startingColor;
gradient = nil; self.gradient = nil;
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
- (void)setEndingColor:(NSColor *)endingColor { - (void)setEndingColor:(NSColor *)endingColor {
_endingColor = endingColor; _endingColor = endingColor;
gradient = nil; self.gradient = nil;
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
- (void)setAngle:(NSInteger)angle { - (void)setAngle:(NSInteger)angle {
_angle = angle; _angle = angle;
gradient = nil; self.gradient = nil;
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
- (void)setRatio:(CGFloat)ratio { - (void)setRatio:(CGFloat)ratio {
_ratio = ratio; _ratio = ratio;
gradient = nil; self.gradient = nil;
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
@ -84,7 +88,7 @@
return; return;
} }
[(gradient?: (gradient = [[NSGradient alloc] initWithColorsAndLocations: [(self.gradient?: (self.gradient = [[NSGradient alloc] initWithColorsAndLocations:
self.startingColor, (CGFloat)0.f, self.startingColor, (CGFloat)0.f,
[self.startingColor blendedColorWithFraction:0.5f ofColor:self.endingColor], self.ratio, [self.startingColor blendedColorWithFraction:0.5f ofColor:self.endingColor], self.ratio,
self.endingColor, (CGFloat)1.f, nil])) self.endingColor, (CGFloat)1.f, nil]))

View File

@ -18,13 +18,13 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "MPAppDelegate_Shared.h" #import "MPAppDelegate_Shared.h"
#import "MPPasswordWindowController.h" #import "MPSitesWindowController.h"
#import "MPInitialWindowController.h" #import "MPInitialWindowController.h"
@interface MPMacAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate> @interface MPMacAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate>
@property(nonatomic, strong) NSStatusItem *statusView; @property(nonatomic, strong) NSStatusItem *statusView;
@property(nonatomic, strong) MPPasswordWindowController *passwordWindowController; @property(nonatomic, strong) MPSitesWindowController *sitesWindowController;
@property(nonatomic, strong) MPInitialWindowController *initialWindowController; @property(nonatomic, strong) MPInitialWindowController *initialWindowController;
@property(nonatomic, weak) IBOutlet NSMenuItem *lockItem; @property(nonatomic, weak) IBOutlet NSMenuItem *lockItem;
@property(nonatomic, weak) IBOutlet NSMenuItem *showItem; @property(nonatomic, weak) IBOutlet NSMenuItem *showItem;

View File

@ -430,8 +430,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
- (IBAction)terminate:(id)sender { - (IBAction)terminate:(id)sender {
[self.passwordWindowController close]; [self.sitesWindowController close];
self.passwordWindowController = nil; self.sitesWindowController = nil;
[NSApp terminate:nil]; [NSApp terminate:nil];
} }
@ -460,11 +460,11 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
prof_rewind( @"activeUserForMainThread" ); prof_rewind( @"activeUserForMainThread" );
// Don't show window if we weren't already running (ie. if we haven't been activated before). // Don't show window if we weren't already running (ie. if we haven't been activated before).
if (!self.passwordWindowController) if (!self.sitesWindowController)
self.passwordWindowController = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"]; self.sitesWindowController = [[MPSitesWindowController alloc] initWithWindowNibName:@"MPSitesWindowController"];
prof_rewind( @"initWithWindow" ); prof_rewind( @"initWithWindow" );
[self.passwordWindowController showWindow:self]; [self.sitesWindowController showWindow:self];
prof_finish( @"showWindow" ); prof_finish( @"showWindow" );
} }
@ -604,7 +604,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
- (void)updateMenuItems { - (void)updateMenuItems {
MPUserEntity *activeUser = [self activeUserForMainThread]; MPUserEntity *activeUser = [self activeUserForMainThread];
// if (!(self.showItem.enabled = ![self.passwordWindowController.window isVisible])) { // if (!(self.showItem.enabled = ![self.sitesWindowController.window isVisible])) {
// self.showItem.title = @"Show (Showing)"; // self.showItem.title = @"Show (Showing)";
// self.showItem.toolTip = @"Master Password is already showing."; // self.showItem.toolTip = @"Master Password is already showing.";
// } // }

View File

@ -25,8 +25,7 @@
@end @end
@implementation MPMacApplication { @implementation MPMacApplication
}
- (void)sendEvent:(NSEvent *)event { - (void)sendEvent:(NSEvent *)event {

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPMacConfig.h // Master Password is free software: you can redistribute it and/or modify
// MasterPassword // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 02/01/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPConfig.h" #import "MPConfig.h"

View File

@ -1,10 +1,20 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
// //
// MPMacConfig.m // Master Password is free software: you can redistribute it and/or modify
// MasterPassword // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by Maarten Billemont on 02/01/12. // Master Password is distributed in the hope that it will be useful,
// Copyright (c) 2012 Lyndir. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
@implementation MPMacConfig @implementation MPMacConfig

View File

@ -1,20 +1,20 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// MPNoStateButton.h // Master Password is free software: you can redistribute it and/or modify
// MPNoStateButton // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by lhunath on 14-10-27. // Master Password is distributed in the hope that it will be useful,
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>

View File

@ -1,25 +1,24 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// MPNoStateButton.h // Master Password is free software: you can redistribute it and/or modify
// MPNoStateButton // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by lhunath on 14-10-27. // Master Password is distributed in the hope that it will be useful,
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPNoStateButton.h" #import "MPNoStateButton.h"
@implementation MPNoStateButtonCell { @implementation MPNoStateButtonCell
}
- (void)setState:(NSInteger)state { - (void)setState:(NSInteger)state {

View File

@ -1,23 +0,0 @@
/**
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
*
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//
// MPPasswordWindow.h
// MPPasswordWindow
//
// Created by lhunath on 2014-06-19.
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface MPPasswordWindow : NSWindow
@end

View File

@ -1,49 +0,0 @@
/**
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
*
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
//
// MPPasswordWindow.h
// MPPasswordWindow
//
// Created by lhunath on 2014-06-19.
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
//
#import "MPPasswordWindow.h"
@implementation MPPasswordWindow
#pragma mark - Life
- (BOOL)canBecomeKeyWindow {
return YES;
}
#pragma mark - State
- (void)update {
if ([[MPMacConfig get].fullScreen boolValue]) {
[self setLevel:NSScreenSaverWindowLevel];
[self setFrame:self.screen.frame display:YES];
}
else if (self.level != NSNormalWindowLevel) {
[self setLevel:NSNormalWindowLevel];
[self setFrame:NSMakeRect( 0, 0, 640, 600 ) display:NO];
[self center];
}
[super update];
}
#pragma mark - Private
@end

View File

@ -7,7 +7,7 @@
<capability name="stacking Non-gravity area distributions on NSStackView" minToolsVersion="7.0" minSystemVersion="10.11"/> <capability name="stacking Non-gravity area distributions on NSStackView" minToolsVersion="7.0" minSystemVersion="10.11"/>
</dependencies> </dependencies>
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordWindowController"> <customObject id="-2" userLabel="File's Owner" customClass="MPSitesWindowController">
<connections> <connections>
<outlet property="inputLabel" destination="OnR-s6-d4P" id="p6G-Ut-cdu"/> <outlet property="inputLabel" destination="OnR-s6-d4P" id="p6G-Ut-cdu"/>
<outlet property="passwordTypesBox" destination="bZe-7q-i6q" id="Ai3-pt-i6K"/> <outlet property="passwordTypesBox" destination="bZe-7q-i6q" id="Ai3-pt-i6K"/>
@ -26,7 +26,7 @@
</customObject> </customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/> <customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Master Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MPPasswordWindow"> <window title="Master Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MPSitesWindow">
<windowStyleMask key="styleMask" texturedBackground="YES" unifiedTitleAndToolbar="YES" fullSizeContentView="YES"/> <windowStyleMask key="styleMask" texturedBackground="YES" unifiedTitleAndToolbar="YES" fullSizeContentView="YES"/>
<windowCollectionBehavior key="collectionBehavior" moveToActiveSpace="YES" transient="YES" ignoresCycle="YES" fullScreenAuxiliary="YES"/> <windowCollectionBehavior key="collectionBehavior" moveToActiveSpace="YES" transient="YES" ignoresCycle="YES" fullScreenAuxiliary="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="640" height="577"/> <rect key="contentRect" x="0.0" y="0.0" width="640" height="577"/>

View File

@ -17,9 +17,9 @@
//============================================================================== //==============================================================================
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "MPSiteEntity.h" #import "MPSiteEntity+CoreDataClass.h"
#import "MPAlgorithm.h" #import "MPAlgorithm.h"
#import "MPUserEntity.h" #import "MPUserEntity+CoreDataClass.h"
@class MPSiteEntity; @class MPSiteEntity;

View File

@ -17,16 +17,19 @@
//============================================================================== //==============================================================================
#import "MPSiteModel.h" #import "MPSiteModel.h"
#import "MPSiteEntity.h"
#import "MPEntities.h" #import "MPEntities.h"
#import "MPAppDelegate_Shared.h" #import "MPAppDelegate_Shared.h"
#import "MPAppDelegate_Store.h" #import "MPAppDelegate_Store.h"
#import "MPMacAppDelegate.h" #import "MPMacAppDelegate.h"
@implementation MPSiteModel { @interface MPSiteModel()
NSManagedObjectID *_entityOID;
BOOL _initialized; @property(nonatomic, strong) NSManagedObjectID *entityOID;
} @property(nonatomic) BOOL initialized;
@end
@implementation MPSiteModel
- (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups { - (instancetype)initWithEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
@ -34,7 +37,7 @@
return nil; return nil;
[self setEntity:entity fuzzyGroups:fuzzyGroups]; [self setEntity:entity fuzzyGroups:fuzzyGroups];
_initialized = YES; self.initialized = YES;
return self; return self;
} }
@ -45,16 +48,16 @@
return nil; return nil;
[self setTransientSiteName:siteName forUser:user]; [self setTransientSiteName:siteName forUser:user];
_initialized = YES; self.initialized = YES;
return self; return self;
} }
- (void)setEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups { - (void)setEntity:(MPSiteEntity *)entity fuzzyGroups:(NSArray *)fuzzyGroups {
if ([_entityOID isEqual:entity.permanentObjectID]) if ([self.entityOID isEqual:entity.permanentObjectID])
return; return;
_entityOID = entity.permanentObjectID; self.entityOID = entity.permanentObjectID;
NSString *siteName = entity.name; NSString *siteName = entity.name;
NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName]; NSMutableAttributedString *attributedSiteName = [[NSMutableAttributedString alloc] initWithString:siteName];
@ -87,7 +90,7 @@
- (void)setTransientSiteName:(NSString *)siteName forUser:(MPUserEntity *)user { - (void)setTransientSiteName:(NSString *)siteName forUser:(MPUserEntity *)user {
_entityOID = nil; self.entityOID = nil;
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = NSCenterTextAlignment; paragraphStyle.alignment = NSCenterTextAlignment;
@ -109,11 +112,11 @@
- (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc { - (MPSiteEntity *)entityInContext:(NSManagedObjectContext *)moc {
if (!_entityOID) if (!self.entityOID)
return nil; return nil;
NSError *error; NSError *error;
MPSiteEntity *entity = (MPSiteEntity *)[moc existingObjectWithID:_entityOID error:&error]; MPSiteEntity *entity = (MPSiteEntity *)[moc existingObjectWithID:self.entityOID error:&error];
if (!entity) if (!entity)
MPError( error, @"Couldn't retrieve active site." ); MPError( error, @"Couldn't retrieve active site." );
@ -122,15 +125,15 @@
- (void)setCounter:(NSUInteger)counter { - (void)setCounter:(NSUInteger)counter {
if (counter == _counter) if (self.counter == counter)
return; return;
_counter = counter; _counter = counter;
if (!_initialized) if (!self.initialized)
// This wasn't a change to the entity. // This wasn't a change to the entity.
return; return;
if (_entityOID) if (self.entityOID)
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *entity = [self entityInContext:context]; MPSiteEntity *entity = [self entityInContext:context];
if ([entity isKindOfClass:[MPGeneratedSiteEntity class]]) { if ([entity isKindOfClass:[MPGeneratedSiteEntity class]]) {
@ -146,15 +149,15 @@
- (void)setLoginGenerated:(BOOL)loginGenerated { - (void)setLoginGenerated:(BOOL)loginGenerated {
if (loginGenerated == _loginGenerated) if (self.loginGenerated == loginGenerated)
return; return;
_loginGenerated = loginGenerated; _loginGenerated = loginGenerated;
if (!_initialized) if (!self.initialized)
// This wasn't a change to the entity. // This wasn't a change to the entity.
return; return;
if (_entityOID) if (self.entityOID)
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *entity = [self entityInContext:context]; MPSiteEntity *entity = [self entityInContext:context];
entity.loginGenerated = loginGenerated; entity.loginGenerated = loginGenerated;
@ -179,7 +182,7 @@
self.algorithm = MPAlgorithmForVersion( algorithmVersion )?: self.algorithm; self.algorithm = MPAlgorithmForVersion( algorithmVersion )?: self.algorithm;
[self didChangeValueForKey:@"outdated"]; [self didChangeValueForKey:@"outdated"];
if (_entityOID) if (self.entityOID)
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *entity = [self entityInContext:context]; MPSiteEntity *entity = [self entityInContext:context];
entity.algorithm = self.algorithm; entity.algorithm = self.algorithm;
@ -193,7 +196,7 @@
- (void)setQuestion:(NSString *)question { - (void)setQuestion:(NSString *)question {
if ([question isEqualToString:_question]) if ([self.question isEqualToString:question])
return; return;
_question = question; _question = question;
@ -217,14 +220,14 @@
- (BOOL)transient { - (BOOL)transient {
return _entityOID == nil; return self.entityOID == nil;
} }
- (void)updateContent { - (void)updateContent {
if (_entityOID) if (self.entityOID)
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
[self updateContent:[MPSiteEntity existingObjectWithID:_entityOID inContext:context]]; [self updateContent:[MPSiteEntity existingObjectWithID:self.entityOID inContext:context]];
}]; }];
else else

View File

@ -18,10 +18,10 @@
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
@class MPPasswordWindowController; @class MPSitesWindowController;
@interface MPSitesTableView : NSTableView @interface MPSitesTableView : NSTableView
@property(nonatomic, weak) MPPasswordWindowController *controller; @property(nonatomic, weak) MPSitesWindowController *controller;
@end @end

View File

@ -17,7 +17,7 @@
//============================================================================== //==============================================================================
#import "MPSitesTableView.h" #import "MPSitesTableView.h"
#import "MPPasswordWindowController.h" #import "MPSitesWindowController.h"
@implementation MPSitesTableView @implementation MPSitesTableView

View File

@ -0,0 +1,23 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Cocoa/Cocoa.h>
@interface MPSitesWindow : NSWindow
@end

View File

@ -0,0 +1,49 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "MPSitesWindow.h"
@implementation MPSitesWindow
#pragma mark - Life
- (BOOL)canBecomeKeyWindow {
return YES;
}
#pragma mark - State
- (void)update {
if ([[MPMacConfig get].fullScreen boolValue]) {
[self setLevel:NSScreenSaverWindowLevel];
[self setFrame:self.screen.frame display:YES];
}
else if (self.level != NSNormalWindowLevel) {
[self setLevel:NSNormalWindowLevel];
[self setFrame:NSMakeRect( 0, 0, 640, 600 ) display:NO];
[self center];
}
[super update];
}
#pragma mark - Private
@end

View File

@ -1,29 +1,29 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// MPPasswordWindowController.h // Master Password is free software: you can redistribute it and/or modify
// MPPasswordWindowController // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by lhunath on 2014-06-18. // Master Password is distributed in the hope that it will be useful,
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "MPSiteModel.h" #import "MPSiteModel.h"
#import "MPSitesTableView.h" #import "MPSitesTableView.h"
#import "MPPasswordWindow.h" #import "MPSitesWindow.h"
@class MPMacAppDelegate; @class MPMacAppDelegate;
@interface MPPasswordWindowController : NSWindowController<NSTextViewDelegate, NSTextFieldDelegate, NSTableViewDataSource, NSTableViewDelegate> @interface MPSitesWindowController : NSWindowController<NSTextViewDelegate, NSTextFieldDelegate, NSTableViewDataSource, NSTableViewDelegate>
@property(nonatomic) NSMutableArray *sites; @property(nonatomic) NSMutableArray *sites;
@property(nonatomic) NSString *masterPassword; @property(nonatomic) NSString *masterPassword;

View File

@ -17,18 +17,18 @@
//============================================================================== //==============================================================================
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
#import "MPPasswordWindowController.h" #import "MPSitesWindowController.h"
#import "MPMacAppDelegate.h" #import "MPMacAppDelegate.h"
#import "MPAppDelegate_Store.h" #import "MPAppDelegate_Store.h"
#import "MPAppDelegate_Key.h" #import "MPAppDelegate_Key.h"
@interface MPPasswordWindowController() @interface MPSitesWindowController()
@property(nonatomic, strong) CAGradientLayer *siteGradient; @property(nonatomic, strong) CAGradientLayer *siteGradient;
@end @end
@implementation MPPasswordWindowController @implementation MPSitesWindowController
#pragma mark - Life #pragma mark - Life
@ -67,8 +67,8 @@
PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue], ^(id host, NSNotification *note) { PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue], ^(id host, NSNotification *note) {
[self updateUser]; [self updateUser];
} ); } );
[self observeKeyPath:@"sitesController.selection" withBlock:^(id from, id to, NSKeyValueChange cause, id _self) { [self observeKeyPath:@"sitesController.selection" withBlock:^(id from, id to, NSKeyValueChange cause, id self) {
[_self updateSelection]; [self updateSelection];
}]; }];
prof_rewind( @"observers" ); prof_rewind( @"observers" );

View File

@ -23,12 +23,12 @@
@interface MPAnswersViewController() @interface MPAnswersViewController()
@property(nonatomic, strong) NSManagedObjectID *siteOID;
@property(nonatomic) BOOL multiple;
@end @end
@implementation MPAnswersViewController { @implementation MPAnswersViewController
NSManagedObjectID *_siteOID;
BOOL _multiple;
}
#pragma mark - Life #pragma mark - Life
@ -80,21 +80,21 @@
- (void)setSite:(MPSiteEntity *)site { - (void)setSite:(MPSiteEntity *)site {
_siteOID = site.permanentObjectID; self.siteOID = site.permanentObjectID;
_multiple = [site.questions count] > 0; self.multiple = [site.questions count] > 0;
[self.tableView reloadData]; [self.tableView reloadData];
[self updateAnimated:NO]; [self updateAnimated:NO];
} }
- (void)setMultiple:(BOOL)multiple animated:(BOOL)animated { - (void)setMultiple:(BOOL)multiple animated:(BOOL)animated {
_multiple = multiple; self.multiple = multiple;
[self updateAnimated:animated]; [self updateAnimated:animated];
} }
- (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context { - (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context {
return [MPSiteEntity existingObjectWithID:_siteOID inContext:context]; return [MPSiteEntity existingObjectWithID:self.siteOID inContext:context];
} }
#pragma mark - UITableViewDelegate #pragma mark - UITableViewDelegate
@ -109,7 +109,7 @@
if (section == 0) if (section == 0)
return 3; return 3;
if (!_multiple) if (!self.multiple)
return 0; return 0;
return [[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].questions count] + 1; return [[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].questions count] + 1;
@ -128,7 +128,7 @@
return [MPSendAnswersCell dequeueCellFromTableView:tableView indexPath:indexPath]; return [MPSendAnswersCell dequeueCellFromTableView:tableView indexPath:indexPath];
if (indexPath.item == 2) { if (indexPath.item == 2) {
MPMultipleAnswersCell *cell = [MPMultipleAnswersCell dequeueCellFromTableView:tableView indexPath:indexPath]; MPMultipleAnswersCell *cell = [MPMultipleAnswersCell dequeueCellFromTableView:tableView indexPath:indexPath];
cell.accessoryType = _multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone; cell.accessoryType = self.multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;
return cell; return cell;
} }
Throw( @"Unsupported row index: %@", indexPath ); Throw( @"Unsupported row index: %@", indexPath );
@ -165,10 +165,10 @@
[self copyAnswer:((MPGlobalAnswersCell *)cell).answerField.text]; [self copyAnswer:((MPGlobalAnswersCell *)cell).answerField.text];
else if ([cell isKindOfClass:[MPMultipleAnswersCell class]]) { else if ([cell isKindOfClass:[MPMultipleAnswersCell class]]) {
if (!_multiple) if (!self.multiple)
[self setMultiple:YES animated:YES]; [self setMultiple:YES animated:YES];
else if (_multiple) { else if (self.multiple) {
if (![site.questions count]) if (![site.questions count])
[self setMultiple:NO animated:YES]; [self setMultiple:NO animated:YES];
@ -194,7 +194,7 @@
else if ([cell isKindOfClass:[MPSendAnswersCell class]]) { else if ([cell isKindOfClass:[MPSendAnswersCell class]]) {
NSString *body; NSString *body;
if (!_multiple) { if (!self.multiple) {
NSObject *answer = [site resolveSiteAnswerUsingKey:[MPiOSAppDelegate get].key]; NSObject *answer = [site resolveSiteAnswerUsingKey:[MPiOSAppDelegate get].key];
body = strf( @"Master Password generated the following security answer for your site: %@\n\n" body = strf( @"Master Password generated the following security answer for your site: %@\n\n"
@"%@\n" @"%@\n"
@ -245,7 +245,7 @@
PearlMainQueue( ^{ PearlMainQueue( ^{
UITableViewCell *multipleAnswersCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:0]]; UITableViewCell *multipleAnswersCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:0]];
multipleAnswersCell.accessoryType = _multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone; multipleAnswersCell.accessoryType = self.multiple? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ [[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
@ -291,19 +291,23 @@
@end @end
@implementation MPAnswersQuestionCell { @interface MPAnswersQuestionCell()
NSManagedObjectID *_siteOID;
NSManagedObjectID *_questionOID; @property(nonatomic, strong) NSManagedObjectID *siteOID;
__weak MPAnswersViewController *_answersVC; @property(nonatomic, strong) NSManagedObjectID *questionOID;
} @property(nonatomic, weak) MPAnswersViewController *answersVC;
@end
@implementation MPAnswersQuestionCell
#pragma mark - State #pragma mark - State
- (void)setQuestion:(MPSiteQuestionEntity *)question forSite:(MPSiteEntity *)site inVC:(MPAnswersViewController *)answersVC { - (void)setQuestion:(MPSiteQuestionEntity *)question forSite:(MPSiteEntity *)site inVC:(MPAnswersViewController *)answersVC {
_siteOID = site.permanentObjectID; self.siteOID = site.permanentObjectID;
_questionOID = question.permanentObjectID; self.questionOID = question.permanentObjectID;
_answersVC = answersVC; self.answersVC = answersVC;
[self updateAnswerForQuestion:question ofSite:site]; [self updateAnswerForQuestion:question ofSite:site];
} }
@ -322,8 +326,8 @@
NSString *keyword = textField.text; NSString *keyword = textField.text;
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
BOOL didAddQuestionObject = NO; BOOL didAddQuestionObject = NO;
MPSiteEntity *site = [MPSiteEntity existingObjectWithID:_siteOID inContext:context]; MPSiteEntity *site = [MPSiteEntity existingObjectWithID:self.siteOID inContext:context];
MPSiteQuestionEntity *question = [MPSiteQuestionEntity existingObjectWithID:_questionOID inContext:context]; MPSiteQuestionEntity *question = [MPSiteQuestionEntity existingObjectWithID:self.questionOID inContext:context];
if (!question) { if (!question) {
didAddQuestionObject = YES; didAddQuestionObject = YES;
[site addQuestionsObject:question = [MPSiteQuestionEntity insertNewObjectInContext:context]]; [site addQuestionsObject:question = [MPSiteQuestionEntity insertNewObjectInContext:context]];
@ -333,11 +337,11 @@
question.keyword = keyword; question.keyword = keyword;
if ([context saveToStore]) { if ([context saveToStore]) {
_questionOID = question.permanentObjectID; self.questionOID = question.permanentObjectID;
[self updateAnswerForQuestion:question ofSite:site]; [self updateAnswerForQuestion:question ofSite:site];
if (didAddQuestionObject) if (didAddQuestionObject)
[_answersVC didAddQuestion:question toSite:site]; [self.answersVC didAddQuestion:question toSite:site];
} }
}]; }];
} }

View File

@ -19,8 +19,7 @@
#import "MPAppSettingsViewController.h" #import "MPAppSettingsViewController.h"
#import "UIColor+Expanded.h" #import "UIColor+Expanded.h"
@implementation MPAppSettingsViewController { @implementation MPAppSettingsViewController
}
- (void)viewWillAppear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated {

View File

@ -32,11 +32,12 @@ const long MPAvatarAdd = 10000;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *avatarRaisedConstraint; @property(strong, nonatomic) IBOutlet NSLayoutConstraint *avatarRaisedConstraint;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *keyboardHeightConstraint; @property(strong, nonatomic) IBOutlet NSLayoutConstraint *keyboardHeightConstraint;
@property(nonatomic, strong) CAAnimationGroup *targetedShadowAnimation;
@property(assign, nonatomic, readwrite) BOOL newUser;
@end @end
@implementation MPAvatarCell { @implementation MPAvatarCell
CAAnimationGroup *_targetedShadowAnimation;
}
+ (NSString *)reuseIdentifier { + (NSString *)reuseIdentifier {
@ -57,14 +58,14 @@ const long MPAvatarAdd = 10000;
self.avatarImageView.layer.masksToBounds = NO; self.avatarImageView.layer.masksToBounds = NO;
self.avatarImageView.backgroundColor = [UIColor clearColor]; self.avatarImageView.backgroundColor = [UIColor clearColor];
[self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *_self) { [self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *self) {
_self.contentView.frame = _self.bounds; self.contentView.frame = self.bounds;
}]; }];
[self observeKeyPath:@"selected" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *_self) { [self observeKeyPath:@"selected" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *self) {
[_self updateAnimated:_self.superview != nil]; [self updateAnimated:self.superview != nil];
}]; }];
[self observeKeyPath:@"highlighted" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *_self) { [self observeKeyPath:@"highlighted" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *self) {
[_self updateAnimated:_self.superview != nil]; [self updateAnimated:self.superview != nil];
}]; }];
PearlAddNotificationObserver( UIKeyboardWillShowNotification, nil, [NSOperationQueue mainQueue], PearlAddNotificationObserver( UIKeyboardWillShowNotification, nil, [NSOperationQueue mainQueue],
^(MPAvatarCell *self, NSNotification *note) { ^(MPAvatarCell *self, NSNotification *note) {
@ -85,9 +86,9 @@ const long MPAvatarAdd = 10000;
pulseShadowOpacityAnimation.autoreverses = YES; pulseShadowOpacityAnimation.autoreverses = YES;
pulseShadowOpacityAnimation.repeatCount = MAXFLOAT; pulseShadowOpacityAnimation.repeatCount = MAXFLOAT;
_targetedShadowAnimation = [CAAnimationGroup new]; self.targetedShadowAnimation = [CAAnimationGroup new];
_targetedShadowAnimation.animations = @[ toShadowOpacityAnimation, pulseShadowOpacityAnimation ]; self.targetedShadowAnimation.animations = @[ toShadowOpacityAnimation, pulseShadowOpacityAnimation ];
_targetedShadowAnimation.duration = MAXFLOAT; self.targetedShadowAnimation.duration = MAXFLOAT;
self.avatarImageView.layer.shadowColor = [UIColor whiteColor].CGColor; self.avatarImageView.layer.shadowColor = [UIColor whiteColor].CGColor;
self.avatarImageView.layer.shadowOffset = CGSizeZero; self.avatarImageView.layer.shadowOffset = CGSizeZero;
} }
@ -96,10 +97,10 @@ const long MPAvatarAdd = 10000;
[super prepareForReuse]; [super prepareForReuse];
_newUser = NO; self.newUser = NO;
_visibility = 0; self.visibility = 0;
_mode = MPAvatarModeLowered; self.mode = MPAvatarModeLowered;
_spinnerActive = NO; self.spinnerActive = NO;
} }
- (void)dealloc { - (void)dealloc {
@ -114,13 +115,13 @@ const long MPAvatarAdd = 10000;
_avatar = avatar == MPAvatarAdd? MPAvatarAdd: (avatar + MPAvatarCount) % MPAvatarCount; _avatar = avatar == MPAvatarAdd? MPAvatarAdd: (avatar + MPAvatarCount) % MPAvatarCount;
if (_avatar == MPAvatarAdd) { if (self.avatar == MPAvatarAdd) {
self.avatarImageView.image = [UIImage imageNamed:@"avatar-add"]; self.avatarImageView.image = [UIImage imageNamed:@"avatar-add"];
self.name = strl( @"New User" ); self.name = strl( @"New User" );
_newUser = YES; self.newUser = YES;
} }
else else
self.avatarImageView.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)_avatar )]; self.avatarImageView.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)self.avatar )];
} }
- (NSString *)name { - (NSString *)name {
@ -140,7 +141,7 @@ const long MPAvatarAdd = 10000;
- (void)setVisibility:(CGFloat)visibility animated:(BOOL)animated { - (void)setVisibility:(CGFloat)visibility animated:(BOOL)animated {
if (visibility == _visibility) if (self.visibility == visibility)
return; return;
_visibility = visibility; _visibility = visibility;
@ -161,7 +162,7 @@ const long MPAvatarAdd = 10000;
- (void)setMode:(MPAvatarMode)mode animated:(BOOL)animated { - (void)setMode:(MPAvatarMode)mode animated:(BOOL)animated {
if (mode == _mode) if (self.mode == mode)
return; return;
_mode = mode; _mode = mode;
@ -175,7 +176,7 @@ const long MPAvatarAdd = 10000;
- (void)setSpinnerActive:(BOOL)spinnerActive animated:(BOOL)animated { - (void)setSpinnerActive:(BOOL)spinnerActive animated:(BOOL)animated {
if (_spinnerActive == spinnerActive) if (self.spinnerActive == spinnerActive)
return; return;
_spinnerActive = spinnerActive; _spinnerActive = spinnerActive;
@ -284,7 +285,7 @@ const long MPAvatarAdd = 10000;
if (self.mode == MPAvatarModeRaisedAndMinimized) if (self.mode == MPAvatarModeRaisedAndMinimized)
[self.avatarImageView.layer removeAnimationForKey:@"targetedShadow"]; [self.avatarImageView.layer removeAnimationForKey:@"targetedShadow"];
else if (![self.avatarImageView.layer animationForKey:@"targetedShadow"]) else if (![self.avatarImageView.layer animationForKey:@"targetedShadow"])
[self.avatarImageView.layer addAnimation:_targetedShadowAnimation forKey:@"targetedShadow"]; [self.avatarImageView.layer addAnimation:self.targetedShadowAnimation forKey:@"targetedShadow"];
// Avatar selection and spinner. // Avatar selection and spinner.
if (self.mode != MPAvatarModeRaisedAndMinimized && (self.selected || self.highlighted) && !self.spinnerActive) if (self.mode != MPAvatarModeRaisedAndMinimized && (self.selected || self.highlighted) && !self.spinnerActive)

View File

@ -18,7 +18,6 @@
#import "MPCell.h" #import "MPCell.h"
@implementation MPCell { @implementation MPCell
}
@end @end

View File

@ -18,17 +18,23 @@
#import "MPCoachmarkViewController.h" #import "MPCoachmarkViewController.h"
@implementation MPCoachmarkViewController { @interface MPCoachmarkViewController()
NSArray *_views;
NSUInteger _nextView; @property(nonatomic, strong) NSArray *views;
__weak NSTimer *_viewTimer; @property(nonatomic) NSUInteger nextView;
} @property(nonatomic, weak) NSTimer *viewTimer;
@end
@implementation MPCoachmarkViewController
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
_views = @[ self.view0, self.view1, self.view2, self.view3, self.view4, self.view5, self.view6, self.view7, self.view8, self.view9 ]; self.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 { - (void)viewWillAppear:(BOOL)animated {
@ -37,8 +43,8 @@
self.viewProgress.visible = YES; self.viewProgress.visible = YES;
self.viewProgress.progress = 0; self.viewProgress.progress = 0;
[_views makeObjectsPerformSelector:@selector( setVisible: ) withObject:@NO]; [self.views makeObjectsPerformSelector:@selector( setVisible: ) withObject:@NO];
_nextView = 0; self.nextView = 0;
} }
- (void)viewDidAppear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated {
@ -46,19 +52,19 @@
[super viewDidAppear:animated]; [super viewDidAppear:animated];
[UIView animateWithDuration:0.3f animations:^{ [UIView animateWithDuration:0.3f animations:^{
[_views[_nextView++] setVisible:YES]; [self.views[self.nextView++] setVisible:YES];
}]; }];
_viewTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimer *timer) { self.viewTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimer *timer) {
self.viewProgress.progress += 1.0f / 50; self.viewProgress.progress += 1.0f / 50;
if (self.viewProgress.progress == 1) if (self.viewProgress.progress == 1)
[UIView animateWithDuration:0.3f animations:^{ [UIView animateWithDuration:0.3f animations:^{
self.viewProgress.progress = 0; self.viewProgress.progress = 0;
[_views[_nextView++] setVisible:YES]; [self.views[self.nextView++] setVisible:YES];
if (_nextView >= [_views count]) { if (self.nextView >= [self.views count]) {
[_viewTimer invalidate]; [self.viewTimer invalidate];
self.viewProgress.visible = NO; self.viewProgress.visible = NO;
} }
}]; }];

View File

@ -17,7 +17,7 @@
//============================================================================== //==============================================================================
#import "MPUsersViewController.h" #import "MPUsersViewController.h"
#import "MPPasswordsViewController.h" #import "MPSitesViewController.h"
#import "MPEmergencyViewController.h" #import "MPEmergencyViewController.h"
typedef NS_ENUM( NSUInteger, MPCombinedMode ) { typedef NS_ENUM( NSUInteger, MPCombinedMode ) {
@ -29,7 +29,7 @@ typedef NS_ENUM( NSUInteger, MPCombinedMode ) {
@property(nonatomic) MPCombinedMode mode; @property(nonatomic) MPCombinedMode mode;
@property(nonatomic, weak) MPUsersViewController *usersVC; @property(nonatomic, weak) MPUsersViewController *usersVC;
@property(nonatomic, weak) MPPasswordsViewController *passwordsVC; @property(nonatomic, weak) MPSitesViewController *sitesVC;
@property(nonatomic, weak) MPEmergencyViewController *emergencyVC; @property(nonatomic, weak) MPEmergencyViewController *emergencyVC;
@end @end

View File

@ -18,9 +18,9 @@
#import "MPCombinedViewController.h" #import "MPCombinedViewController.h"
#import "MPUsersViewController.h" #import "MPUsersViewController.h"
#import "MPPasswordsViewController.h" #import "MPSitesViewController.h"
#import "MPEmergencyViewController.h" #import "MPEmergencyViewController.h"
#import "MPPasswordsSegue.h" #import "MPSitesSegue.h"
@implementation MPCombinedViewController @implementation MPCombinedViewController
@ -30,7 +30,7 @@
[super viewDidLoad]; [super viewDidLoad];
_mode = MPCombinedModeUserSelection; self.mode = MPCombinedModeUserSelection;
[self performSegueWithIdentifier:@"users" sender:self]; [self performSegueWithIdentifier:@"users" sender:self];
} }
@ -67,12 +67,12 @@
if ([segue.identifier isEqualToString:@"users"]) if ([segue.identifier isEqualToString:@"users"])
self.usersVC = segue.destinationViewController; self.usersVC = segue.destinationViewController;
if ([segue.identifier isEqualToString:@"passwords"]) { if ([segue.identifier isEqualToString:@"passwords"]) {
NSAssert( [segue isKindOfClass:[MPPasswordsSegue class]], @"passwords segue should be MPPasswordsSegue: %@", segue ); NSAssert( [segue isKindOfClass:[MPSitesSegue class]], @"passwords segue should be MPSitesSegue: %@", segue );
NSAssert( [sender isKindOfClass:[NSDictionary class]], @"sender should be dictionary: %@", sender ); NSAssert( [sender isKindOfClass:[NSDictionary class]], @"sender should be dictionary: %@", sender );
NSAssert( [[sender objectForKey:@"animated"] isKindOfClass:[NSNumber class]], @"sender should contain 'animated': %@", sender ); NSAssert( [[sender objectForKey:@"animated"] isKindOfClass:[NSNumber class]], @"sender should contain 'animated': %@", sender );
[(MPPasswordsSegue *)segue setAnimated:[sender[@"animated"] boolValue]]; [(MPSitesSegue *)segue setAnimated:[sender[@"animated"] boolValue]];
UIViewController *destinationVC = segue.destinationViewController; UIViewController *destinationVC = segue.destinationViewController;
_passwordsVC = [destinationVC isKindOfClass:[MPPasswordsViewController class]]? (MPPasswordsViewController *)destinationVC: nil; self.sitesVC = [destinationVC isKindOfClass:[MPSitesViewController class]]? (MPSitesViewController *)destinationVC: nil;
} }
if ([segue.identifier isEqualToString:@"emergency"]) if ([segue.identifier isEqualToString:@"emergency"])
self.emergencyVC = segue.destinationViewController; self.emergencyVC = segue.destinationViewController;
@ -115,7 +115,7 @@
- (void)setMode:(MPCombinedMode)mode animated:(BOOL)animated { - (void)setMode:(MPCombinedMode)mode animated:(BOOL)animated {
if (_mode == mode && animated) if (self.mode == mode && animated)
return; return;
_mode = mode; _mode = mode;
@ -129,8 +129,8 @@
case MPCombinedModeUserSelection: { case MPCombinedModeUserSelection: {
self.usersVC.view.userInteractionEnabled = YES; self.usersVC.view.userInteractionEnabled = YES;
[self.usersVC setActive:YES animated:animated]; [self.usersVC setActive:YES animated:animated];
if (_passwordsVC) { if (self.sitesVC) {
MPPasswordsSegue *segue = [[MPPasswordsSegue alloc] initWithIdentifier:@"passwords" source:_passwordsVC destination:self]; MPSitesSegue *segue = [[MPSitesSegue alloc] initWithIdentifier:@"passwords" source:self.sitesVC destination:self];
[self prepareForSegue:segue sender:@{ @"animated": @(animated) }]; [self prepareForSegue:segue sender:@{ @"animated": @(animated) }];
[segue perform]; [segue perform];
} }

View File

@ -19,18 +19,22 @@
#import "MPEmergencyViewController.h" #import "MPEmergencyViewController.h"
#import "MPEntities.h" #import "MPEntities.h"
@implementation MPEmergencyViewController { @interface MPEmergencyViewController()
MPKey *_key;
NSOperationQueue *_emergencyKeyQueue; @property(nonatomic, strong) MPKey *key;
NSOperationQueue *_emergencyPasswordQueue; @property(nonatomic, strong) NSOperationQueue *emergencyKeyQueue;
} @property(nonatomic, strong) NSOperationQueue *emergencyPasswordQueue;
@end
@implementation MPEmergencyViewController
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
[_emergencyKeyQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1]; [self.emergencyKeyQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1];
[_emergencyPasswordQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1]; [self.emergencyPasswordQueue = [NSOperationQueue new] setMaxConcurrentOperationCount:1];
self.view.backgroundColor = [UIColor clearColor]; self.view.backgroundColor = [UIColor clearColor];
self.dialogView.layer.cornerRadius = 5; self.dialogView.layer.cornerRadius = 5;
@ -117,12 +121,12 @@
[self.passwordButton setTitle:nil forState:UIControlStateNormal]; [self.passwordButton setTitle:nil forState:UIControlStateNormal];
[self.activity startAnimating]; [self.activity startAnimating];
[_emergencyKeyQueue cancelAllOperations]; [self.emergencyKeyQueue cancelAllOperations];
[_emergencyKeyQueue addOperationWithBlock:^{ [self.emergencyKeyQueue addOperationWithBlock:^{
if ([masterPassword length] && [fullName length]) if ([masterPassword length] && [fullName length])
_key = [[MPKey alloc] initForFullName:fullName withMasterPassword:masterPassword]; self.key = [[MPKey alloc] initForFullName:fullName withMasterPassword:masterPassword];
else else
_key = nil; self.key = nil;
PearlMainQueue( ^{ PearlMainQueue( ^{
[self updatePassword]; [self updatePassword];
@ -139,11 +143,12 @@
[self.passwordButton setTitle:nil forState:UIControlStateNormal]; [self.passwordButton setTitle:nil forState:UIControlStateNormal];
[self.activity startAnimating]; [self.activity startAnimating];
[_emergencyPasswordQueue cancelAllOperations]; [self.emergencyPasswordQueue cancelAllOperations];
[_emergencyPasswordQueue addOperationWithBlock:^{ [self.emergencyPasswordQueue addOperationWithBlock:^{
NSString *sitePassword = nil; NSString *sitePassword = nil;
if (_key && [siteName length]) if (self.key && [siteName length])
sitePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:siteName ofType:siteType withCounter:siteCounter usingKey:_key]; sitePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:siteName ofType:siteType withCounter:siteCounter
usingKey:self.key];
PearlMainQueue( ^{ PearlMainQueue( ^{
[self.activity stopAnimating]; [self.activity stopAnimating];

View File

@ -18,15 +18,19 @@
#import "MPOverlayViewController.h" #import "MPOverlayViewController.h"
@implementation MPOverlayViewController { @interface MPOverlayViewController()
NSMutableDictionary *_dismissSegueByButton;
} @property(nonatomic, strong) NSMutableDictionary *dismissSegueByButton;
@end
@implementation MPOverlayViewController
- (void)awakeFromNib { - (void)awakeFromNib {
[super awakeFromNib]; [super awakeFromNib];
_dismissSegueByButton = [NSMutableDictionary dictionary]; self.dismissSegueByButton = [NSMutableDictionary dictionary];
} }
- (void)viewDidLoad { - (void)viewDidLoad {
@ -60,7 +64,7 @@
dismissButton.visible = NO; dismissButton.visible = NO;
dismissButton.frame = self.view.bounds; dismissButton.frame = self.view.bounds;
dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] = self.dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] =
[[MPOverlaySegue alloc] initWithIdentifier:@"dismiss-overlay" [[MPOverlaySegue alloc] initWithIdentifier:@"dismiss-overlay"
source:segue.destinationViewController destination:segue.sourceViewController]; source:segue.destinationViewController destination:segue.sourceViewController];
@ -71,14 +75,14 @@
- (void)dismissOverlay:(UIButton *)dismissButton { - (void)dismissOverlay:(UIButton *)dismissButton {
NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton]; NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton];
[((UIStoryboardSegue *)_dismissSegueByButton[dismissSegueKey]) perform]; [((UIStoryboardSegue *)self.dismissSegueByButton[dismissSegueKey]) perform];
} }
- (void)removeDismissButtonForViewController:(UIViewController *)viewController { - (void)removeDismissButtonForViewController:(UIViewController *)viewController {
UIButton *dismissButton = nil; UIButton *dismissButton = nil;
for (NSValue *dismissButtonValue in [_dismissSegueByButton allKeys]) for (NSValue *dismissButtonValue in [self.dismissSegueByButton allKeys])
if (((UIStoryboardSegue *)_dismissSegueByButton[dismissButtonValue]).sourceViewController == viewController) { if (((UIStoryboardSegue *)self.dismissSegueByButton[dismissButtonValue]).sourceViewController == viewController) {
dismissButton = [dismissButtonValue nonretainedObjectValue]; dismissButton = [dismissButtonValue nonretainedObjectValue];
NSAssert( [self.view.subviews containsObject:dismissButton], @"Missing dismiss button in dictionary." ); NSAssert( [self.view.subviews containsObject:dismissButton], @"Missing dismiss button in dictionary." );
} }
@ -86,7 +90,7 @@
return; return;
NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton]; NSValue *dismissSegueKey = [NSValue valueWithNonretainedObject:dismissButton];
[_dismissSegueByButton removeObjectForKey:dismissSegueKey]; [self.dismissSegueByButton removeObjectForKey:dismissSegueKey];
[UIView animateWithDuration:0.1f animations:^{ [UIView animateWithDuration:0.1f animations:^{
dismissButton.visible = NO; dismissButton.visible = NO;

View File

@ -17,16 +17,15 @@
//============================================================================== //==============================================================================
#import "MPPopdownSegue.h" #import "MPPopdownSegue.h"
#import "MPPasswordsViewController.h" #import "MPSitesViewController.h"
@implementation MPPopdownSegue { @implementation MPPopdownSegue
}
- (void)perform { - (void)perform {
MPPasswordsViewController *passwordsVC; MPSitesViewController *passwordsVC;
UIViewController *popdownVC; UIViewController *popdownVC;
if ([self.sourceViewController isKindOfClass:[MPPasswordsViewController class]]) { if ([self.sourceViewController isKindOfClass:[MPSitesViewController class]]) {
passwordsVC = self.sourceViewController; passwordsVC = self.sourceViewController;
popdownVC = self.destinationViewController; popdownVC = self.destinationViewController;
UIView *popdownView = popdownVC.view; UIView *popdownView = popdownVC.view;
@ -55,7 +54,7 @@
} }
else { else {
popdownVC = self.sourceViewController; popdownVC = self.sourceViewController;
for (passwordsVC = self.sourceViewController; passwordsVC && ![(id)passwordsVC isKindOfClass:[MPPasswordsViewController class]]; for (passwordsVC = self.sourceViewController; passwordsVC && ![(id)passwordsVC isKindOfClass:[MPSitesViewController class]];
passwordsVC = (id)passwordsVC.parentViewController); passwordsVC = (id)passwordsVC.parentViewController);
NSAssert( passwordsVC, @"Couldn't find passwords VC to pop back to." ); NSAssert( passwordsVC, @"Couldn't find passwords VC to pop back to." );

View File

@ -32,7 +32,7 @@
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated1TypeControl; @property(weak, nonatomic) IBOutlet UISegmentedControl *generated1TypeControl;
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated2TypeControl; @property(weak, nonatomic) IBOutlet UISegmentedControl *generated2TypeControl;
@property(weak, nonatomic) IBOutlet UISegmentedControl *storedTypeControl; @property(weak, nonatomic) IBOutlet UISegmentedControl *storedTypeControl;
@property(weak, nonatomic) IBOutlet UILabel *passwordTypeExample; @property(weak, nonatomic) IBOutlet UILabel *typeSamplePassword;
- (IBAction)previousAvatar:(id)sender; - (IBAction)previousAvatar:(id)sender;
- (IBAction)nextAvatar:(id)sender; - (IBAction)nextAvatar:(id)sender;

View File

@ -21,7 +21,7 @@
#import "MPAppDelegate_Key.h" #import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h" #import "MPAppDelegate_Store.h"
#import "UIColor+Expanded.h" #import "UIColor+Expanded.h"
#import "MPPasswordsViewController.h" #import "MPSitesViewController.h"
#import "MPAppDelegate_InApp.h" #import "MPAppDelegate_InApp.h"
@interface MPPreferencesViewController() @interface MPPreferencesViewController()
@ -70,7 +70,7 @@
examplePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:@"test" ofType:defaultType examplePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:@"test" ofType:defaultType
withCounter:1 usingKey:[MPiOSAppDelegate get].key]; withCounter:1 usingKey:[MPiOSAppDelegate get].key];
PearlMainQueue( ^{ PearlMainQueue( ^{
self.passwordTypeExample.text = [examplePassword length]? [NSString stringWithFormat:@"eg. %@", examplePassword]: nil; self.typeSamplePassword.text = [examplePassword length]? [NSString stringWithFormat:@"eg. %@", examplePassword]: nil;
} ); } );
} ); } );
} }
@ -108,7 +108,7 @@
[[MPiOSAppDelegate get] showExportForVC:self]; [[MPiOSAppDelegate get] showExportForVC:self];
if (cell == self.showHelpCell) { if (cell == self.showHelpCell) {
MPPasswordsViewController *passwordsVC = [self dismissPopup]; MPSitesViewController *passwordsVC = [self dismissPopup];
[passwordsVC performSegueWithIdentifier:@"guide" sender:self]; [passwordsVC performSegueWithIdentifier:@"guide" sender:self];
} }
@ -230,11 +230,11 @@
#pragma mark - Private #pragma mark - Private
- (MPPasswordsViewController *)dismissPopup { - (MPSitesViewController *)dismissPopup {
for (UIViewController *vc = self; (vc = vc.parentViewController);) for (UIViewController *vc = self; (vc = vc.parentViewController);)
if ([vc isKindOfClass:[MPPasswordsViewController class]]) { if ([vc isKindOfClass:[MPSitesViewController class]]) {
MPPasswordsViewController *passwordsVC = (MPPasswordsViewController *)vc; MPSitesViewController *passwordsVC = (MPSitesViewController *)vc;
[passwordsVC dismissPopdown:self]; [passwordsVC dismissPopdown:self];
return passwordsVC; return passwordsVC;
} }

View File

@ -18,8 +18,7 @@
#import "MPRootSegue.h" #import "MPRootSegue.h"
@implementation MPRootSegue { @implementation MPRootSegue
}
- (void)perform { - (void)perform {

View File

@ -20,18 +20,18 @@
#import "MPEntities.h" #import "MPEntities.h"
#import "MPCell.h" #import "MPCell.h"
typedef NS_ENUM ( NSUInteger, MPPasswordCellMode ) { typedef NS_ENUM ( NSUInteger, MPSiteCellMode ) {
MPPasswordCellModePassword, MPPasswordCellModePassword,
MPPasswordCellModeSettings, MPPasswordCellModeSettings,
}; };
@interface MPPasswordCell : MPCell<UIScrollViewDelegate, UITextFieldDelegate> @interface MPSiteCell : MPCell<UIScrollViewDelegate, UITextFieldDelegate>
@property(nonatomic) NSArray *fuzzyGroups; @property(nonatomic) NSArray *fuzzyGroups;
- (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated; - (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated;
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated; - (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated; - (void)setMode:(MPSiteCellMode)mode animated:(BOOL)animated;
- (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context; - (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context;
@end @end

View File

@ -16,13 +16,12 @@
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>. // LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//============================================================================== //==============================================================================
#import "MPPasswordCell.h" #import "MPSiteCell.h"
#import "MPiOSAppDelegate.h" #import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Store.h" #import "MPAppDelegate_Store.h"
#import "UIColor+Expanded.h"
#import "MPAppDelegate_InApp.h" #import "MPAppDelegate_InApp.h"
@interface MPPasswordCell() @interface MPSiteCell()
@property(nonatomic, strong) IBOutlet UILabel *siteNameLabel; @property(nonatomic, strong) IBOutlet UILabel *siteNameLabel;
@property(nonatomic, strong) IBOutlet UITextField *passwordField; @property(nonatomic, strong) IBOutlet UITextField *passwordField;
@ -41,14 +40,13 @@
@property(nonatomic, strong) IBOutlet UIButton *loginNameButton; @property(nonatomic, strong) IBOutlet UIButton *loginNameButton;
@property(nonatomic, strong) IBOutlet UIView *indicatorView; @property(nonatomic, strong) IBOutlet UIView *indicatorView;
@property(nonatomic) MPPasswordCellMode mode; @property(nonatomic) MPSiteCellMode mode;
@property(nonatomic, copy) NSString *transientSite; @property(nonatomic, copy) NSString *transientSite;
@property(nonatomic, strong) NSManagedObjectID *siteOID;
@end @end
@implementation MPPasswordCell { @implementation MPSiteCell
NSManagedObjectID *_siteOID;
}
#pragma mark - Life cycle #pragma mark - Life cycle
@ -65,9 +63,9 @@
[self setupLayer]; [self setupLayer];
[self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPPasswordCell *_self) { [self observeKeyPath:@"bounds" withBlock:^(id from, id to, NSKeyValueChange cause, MPSiteCell *self) {
if (from && !CGSizeEqualToSize( [from CGRectValue].size, [to CGRectValue].size )) if (from && !CGSizeEqualToSize( [from CGRectValue].size, [to CGRectValue].size ))
[_self setupLayer]; [self setupLayer];
}]; }];
[self.contentButton observeKeyPath:@"highlighted" [self.contentButton observeKeyPath:@"highlighted"
withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) { withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) {
@ -135,8 +133,8 @@
[super prepareForReuse]; [super prepareForReuse];
_siteOID = nil; self.siteOID = nil;
_fuzzyGroups = nil; self.fuzzyGroups = nil;
self.transientSite = nil; self.transientSite = nil;
self.mode = MPPasswordCellModePassword; self.mode = MPPasswordCellModePassword;
[self updateAnimated:NO]; [self updateAnimated:NO];
@ -153,25 +151,25 @@
- (void)setFuzzyGroups:(NSArray *)fuzzyGroups { - (void)setFuzzyGroups:(NSArray *)fuzzyGroups {
if (_fuzzyGroups == fuzzyGroups) if (self.fuzzyGroups == fuzzyGroups)
return; return;
_fuzzyGroups = fuzzyGroups; _fuzzyGroups = fuzzyGroups;
[self updateSiteName:[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]]; [self updateSiteName:[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]];
} }
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated { - (void)setMode:(MPSiteCellMode)mode animated:(BOOL)animated {
if (mode == _mode) if (self.mode == mode)
return; return;
_mode = mode; _mode = mode;
[self updateAnimated:animated]; [self updateAnimated:animated];
} }
- (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated { - (void)setSite:(MPSiteEntity *)site animated:(BOOL)animated {
_siteOID = site.permanentObjectID; self.siteOID = site.permanentObjectID;
[self updateAnimated:animated]; [self updateAnimated:animated];
} }
@ -531,7 +529,7 @@
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]; MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
// UI // UI
self.backgroundColor = mainSite.url? [UIColor greenColor]: [UIColor redColor]; //self.backgroundColor = mainSite.url? [UIColor greenColor]: [UIColor redColor];
self.upgradeButton.gone = !mainSite.requiresExplicitMigration && ![[MPiOSConfig get].allowDowngrade boolValue]; self.upgradeButton.gone = !mainSite.requiresExplicitMigration && ![[MPiOSConfig get].allowDowngrade boolValue];
self.answersButton.gone = ![[MPiOSAppDelegate get] isFeatureUnlocked:MPProductGenerateAnswers]; self.answersButton.gone = ![[MPiOSAppDelegate get] isFeatureUnlocked:MPProductGenerateAnswers];
BOOL settingsMode = self.mode == MPPasswordCellModeSettings; BOOL settingsMode = self.mode == MPPasswordCellModeSettings;
@ -718,7 +716,7 @@
- (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context { - (MPSiteEntity *)siteInContext:(NSManagedObjectContext *)context {
return [MPSiteEntity existingObjectWithID:_siteOID inContext:context]; return [MPSiteEntity existingObjectWithID:self.siteOID inContext:context];
} }
@end @end

View File

@ -18,7 +18,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@interface MPPasswordsSegue : UIStoryboardSegue @interface MPSitesSegue : UIStoryboardSegue
@property(nonatomic, assign) BOOL animated; @property(nonatomic, assign) BOOL animated;

View File

@ -16,12 +16,11 @@
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>. // LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//============================================================================== //==============================================================================
#import "MPPasswordsSegue.h" #import "MPSitesSegue.h"
#import "MPPasswordsViewController.h" #import "MPSitesViewController.h"
#import "MPCombinedViewController.h" #import "MPCombinedViewController.h"
@implementation MPPasswordsSegue { @implementation MPSitesSegue
}
- (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination { - (id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination {
@ -35,34 +34,34 @@
- (void)perform { - (void)perform {
if ([self.destinationViewController isKindOfClass:[MPPasswordsViewController class]]) { if ([self.destinationViewController isKindOfClass:[MPSitesViewController class]]) {
__weak MPPasswordsViewController *passwordsVC = self.destinationViewController; __weak MPSitesViewController *sitesVC = self.destinationViewController;
MPCombinedViewController *combinedVC = self.sourceViewController; MPCombinedViewController *combinedVC = self.sourceViewController;
[combinedVC addChildViewController:passwordsVC]; [combinedVC addChildViewController:sitesVC];
passwordsVC.active = NO; sitesVC.active = NO;
UIView *passwordsView = passwordsVC.view; UIView *sitesView = sitesVC.view;
passwordsView.frame = combinedVC.view.bounds; sitesView.frame = combinedVC.view.bounds;
passwordsView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; sitesView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[combinedVC.view insertSubview:passwordsView belowSubview:combinedVC.usersVC.view]; [combinedVC.view insertSubview:sitesView belowSubview:combinedVC.usersVC.view];
[passwordsVC setActive:YES animated:self.animated completion:^(BOOL finished) { [sitesVC setActive:YES animated:self.animated completion:^(BOOL finished) {
if (!finished) if (!finished)
return; return;
[passwordsVC didMoveToParentViewController:combinedVC]; [sitesVC didMoveToParentViewController:combinedVC];
}]; }];
} }
else if ([self.sourceViewController isKindOfClass:[MPPasswordsViewController class]]) { else if ([self.sourceViewController isKindOfClass:[MPSitesViewController class]]) {
__weak MPPasswordsViewController *passwordsVC = self.sourceViewController; __weak MPSitesViewController *sitesVC = self.sourceViewController;
[passwordsVC willMoveToParentViewController:nil]; [sitesVC willMoveToParentViewController:nil];
[passwordsVC setActive:NO animated:self.animated completion:^(BOOL finished) { [sitesVC setActive:NO animated:self.animated completion:^(BOOL finished) {
if (!finished) if (!finished)
return; return;
[passwordsVC.view removeFromSuperview]; [sitesVC.view removeFromSuperview];
[passwordsVC removeFromParentViewController]; [sitesVC removeFromParentViewController];
}]; }];
} }
} }

View File

@ -19,22 +19,22 @@
@class MPSiteEntity; @class MPSiteEntity;
@class MPCoachmark; @class MPCoachmark;
@interface MPPasswordsViewController : UIViewController<UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> @interface MPSitesViewController : UIViewController<UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property(strong, nonatomic) IBOutlet UIView *passwordSelectionContainer; @property(nonatomic, strong) IBOutlet UICollectionView *collectionView;
@property(strong, nonatomic) IBOutlet UICollectionView *passwordCollectionView; @property(nonatomic, strong) IBOutlet UINavigationBar *navigationBar;
@property(strong, nonatomic) IBOutlet UISearchBar *passwordsSearchBar; @property(nonatomic, strong) IBOutlet UISearchBar *searchBar;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *passwordsToBottomConstraint; @property(nonatomic, strong) IBOutlet NSLayoutConstraint *sitesToBottomConstraint;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *navigationBarToTopConstraint; @property(nonatomic, strong) IBOutlet NSLayoutConstraint *navigationBarToTopConstraint;
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *popdownToTopConstraint; @property(nonatomic, strong) IBOutlet NSLayoutConstraint *popdownToTopConstraint;
@property(strong, nonatomic) IBOutlet UIView *badNameTipContainer; @property(nonatomic, strong) IBOutlet UIView *badNameTipContainer;
@property(strong, nonatomic) IBOutlet UIView *popdownView; @property(nonatomic, strong) IBOutlet UIView *popdownView;
@property(strong, nonatomic) IBOutlet UIView *popdownContainer; @property(nonatomic, strong) IBOutlet UIView *popdownContainer;
@property(assign, nonatomic) BOOL active; @property(assign, nonatomic) BOOL active;
- (void)setActive:(BOOL)active animated:(BOOL)animated completion:(void ( ^ )(BOOL finished))completion; - (void)setActive:(BOOL)active animated:(BOOL)animated completion:(void ( ^ )(BOOL finished))completion;
- (void)reloadPasswords; - (void)reloadSites;
- (IBAction)dismissPopdown:(id)sender; - (IBAction)dismissPopdown:(id)sender;

View File

@ -16,12 +16,12 @@
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>. // LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//============================================================================== //==============================================================================
#import "MPPasswordsViewController.h" #import "MPSitesViewController.h"
#import "MPiOSAppDelegate.h" #import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Store.h" #import "MPAppDelegate_Store.h"
#import "MPPopdownSegue.h" #import "MPPopdownSegue.h"
#import "MPAppDelegate_Key.h" #import "MPAppDelegate_Key.h"
#import "MPPasswordCell.h" #import "MPSiteCell.h"
#import "MPAnswersViewController.h" #import "MPAnswersViewController.h"
#import "MPMessageViewController.h" #import "MPMessageViewController.h"
@ -31,22 +31,17 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
MPPasswordsBadNameTip = 1 << 0, MPPasswordsBadNameTip = 1 << 0,
}; };
@interface MPPasswordsViewController()<NSFetchedResultsControllerDelegate> @interface MPSitesViewController()<NSFetchedResultsControllerDelegate>
@property(nonatomic, strong) IBOutlet UINavigationBar *navigationBar; @property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@property(nonatomic, strong) NSArray *fuzzyGroups;
@property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet;
@property(nonatomic, strong) NSMutableArray<NSMutableArray *> *dataSource;
@property(nonatomic, weak) UIViewController *popdownVC;
@end @end
@implementation MPPasswordsViewController { @implementation MPSitesViewController
__weak UITapGestureRecognizer *_passwordsDismissRecognizer;
NSFetchedResultsController *_fetchedResultsController;
UIColor *_backgroundColor;
UIColor *_darkenedBackgroundColor;
__weak UIViewController *_popdownVC;
NSCharacterSet *_siteNameAcceptableCharactersSet;
NSArray *_fuzzyGroups;
NSMutableArray<NSMutableArray *> *_passwordCollectionSections;
}
#pragma mark - Life #pragma mark - Life
@ -57,19 +52,17 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
NSMutableCharacterSet *siteNameAcceptableCharactersSet = [[NSCharacterSet alphanumericCharacterSet] mutableCopy]; NSMutableCharacterSet *siteNameAcceptableCharactersSet = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[siteNameAcceptableCharactersSet formIntersectionWithCharacterSet:[[NSCharacterSet uppercaseLetterCharacterSet] invertedSet]]; [siteNameAcceptableCharactersSet formIntersectionWithCharacterSet:[[NSCharacterSet uppercaseLetterCharacterSet] invertedSet]];
[siteNameAcceptableCharactersSet addCharactersInString:@"@.-+~&_;:/"]; [siteNameAcceptableCharactersSet addCharactersInString:@"@.-+~&_;:/"];
_siteNameAcceptableCharactersSet = siteNameAcceptableCharactersSet; self.siteNameAcceptableCharactersSet = siteNameAcceptableCharactersSet;
_backgroundColor = self.passwordCollectionView.backgroundColor; self.dataSource = [NSMutableArray new];
_darkenedBackgroundColor = [_backgroundColor colorWithAlphaComponent:0.6f];
_passwordCollectionSections = [NSMutableArray new];
self.view.backgroundColor = [UIColor clearColor]; self.view.backgroundColor = [UIColor clearColor];
[self.passwordCollectionView automaticallyAdjustInsetsForKeyboard]; [self.collectionView automaticallyAdjustInsetsForKeyboard];
self.passwordsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone; self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
if ([self.passwordsSearchBar respondsToSelector:@selector( keyboardAppearance )]) if ([self.searchBar respondsToSelector:@selector( keyboardAppearance )])
self.passwordsSearchBar.keyboardAppearance = UIKeyboardAppearanceDark; self.searchBar.keyboardAppearance = UIKeyboardAppearanceDark;
else else
[self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) { [self.searchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
if ([subview isKindOfClass:[UITextField class]]) if ([subview isKindOfClass:[UITextField class]])
((UITextField *)subview).keyboardAppearance = UIKeyboardAppearanceDark; ((UITextField *)subview).keyboardAppearance = UIKeyboardAppearanceDark;
} recurse:YES]; } recurse:YES];
@ -98,7 +91,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
if (pasteboardURL.host) if (pasteboardURL.host)
self.query = NSNullToNil( [pasteboardURL.host firstMatchGroupsOfExpression:bareHostRE][0] ); self.query = NSNullToNil( [pasteboardURL.host firstMatchGroupsOfExpression:bareHostRE][0] );
else else
[self reloadPasswords]; [self reloadSites];
} }
- (void)viewDidAppear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated {
@ -131,17 +124,17 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"popdown"]) if ([segue.identifier isEqualToString:@"popdown"])
_popdownVC = segue.destinationViewController; self.popdownVC = segue.destinationViewController;
if ([segue.identifier isEqualToString:@"answers"]) if ([segue.identifier isEqualToString:@"answers"])
((MPAnswersViewController *)segue.destinationViewController).site = ((MPAnswersViewController *)segue.destinationViewController).site =
[[MPPasswordCell findAsSuperviewOf:sender] siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]]; [[MPSiteCell findAsSuperviewOf:sender] siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
if ([segue.identifier isEqualToString:@"message"]) if ([segue.identifier isEqualToString:@"message"])
((MPMessageViewController *)segue.destinationViewController).message = sender; ((MPMessageViewController *)segue.destinationViewController).message = sender;
} }
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[self.passwordCollectionView.collectionViewLayout invalidateLayout]; [self.collectionView.collectionViewLayout invalidateLayout];
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
} }
@ -159,7 +152,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
insetForSectionAtIndex:(NSInteger)section { insetForSectionAtIndex:(NSInteger)section {
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout; UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)collectionViewLayout;
UIEdgeInsets occludedInsets = [self.passwordCollectionView occludedInsets]; UIEdgeInsets occludedInsets = [self.collectionView occludedInsets];
UIEdgeInsets insets = layout.sectionInset; UIEdgeInsets insets = layout.sectionInset;
insets.top = insets.bottom; // Undo storyboard hack for manual top-occluded insets. insets.top = insets.bottom; // Undo storyboard hack for manual top-occluded insets.
@ -176,19 +169,19 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return [_passwordCollectionSections count]; return [self.dataSource count];
} }
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [_passwordCollectionSections[(NSUInteger)section] count]; return [self.dataSource[(NSUInteger)section] count];
} }
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MPPasswordCell *cell = [MPPasswordCell dequeueCellFromCollectionView:collectionView indexPath:indexPath]; MPSiteCell *cell = [MPSiteCell dequeueCellFromCollectionView:collectionView indexPath:indexPath];
[cell setFuzzyGroups:_fuzzyGroups]; [cell setFuzzyGroups:self.fuzzyGroups];
id item = _passwordCollectionSections[(NSUInteger)indexPath.section][(NSUInteger)indexPath.item]; id item = self.dataSource[(NSUInteger)indexPath.section][(NSUInteger)indexPath.item];
if ([item isKindOfClass:[MPSiteEntity class]]) if ([item isKindOfClass:[MPSiteEntity class]])
[cell setSite:item animated:NO]; [cell setSite:item animated:NO];
else // item == MPTransientPasswordItem else // item == MPTransientPasswordItem
@ -201,8 +194,8 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if (scrollView == self.passwordCollectionView) if (scrollView == self.collectionView)
for (MPPasswordCell *cell in [self.passwordCollectionView visibleCells]) for (MPSiteCell *cell in [self.collectionView visibleCells])
[cell setMode:MPPasswordCellModePassword animated:YES]; [cell setMode:MPPasswordCellModePassword animated:YES];
} }
@ -210,9 +203,9 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
if (controller == _fetchedResultsController) if (controller == self.fetchedResultsController)
PearlMainQueue( ^{ PearlMainQueue( ^{
[self.passwordCollectionView updateDataSource:_passwordCollectionSections [self.collectionView updateDataSource:self.dataSource
toSections:[self createPasswordCollectionSections] toSections:[self createPasswordCollectionSections]
reloadItems:nil completion:nil]; reloadItems:nil completion:nil];
} ); } );
@ -222,7 +215,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar { - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
if (searchBar == self.passwordsSearchBar) { if (searchBar == self.searchBar) {
searchBar.text = nil; searchBar.text = nil;
return YES; return YES;
} }
@ -232,24 +225,22 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
if (searchBar == self.passwordsSearchBar) { if (searchBar == self.searchBar) {
[self.passwordsSearchBar setShowsCancelButton:YES animated:YES]; [self.searchBar setShowsCancelButton:YES animated:YES];
[UIView animateWithDuration:0.3f animations:^{ [UIView animateWithDuration:0.3f animations:^{
self.passwordCollectionView.backgroundColor = _darkenedBackgroundColor; self.collectionView.backgroundColor = [self.collectionView.backgroundColor colorWithAlphaComponent:0.6f];
}]; }];
} }
} }
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar { - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
if (searchBar == self.passwordsSearchBar) { if (searchBar == self.searchBar) {
[self.passwordsSearchBar setShowsCancelButton:NO animated:YES]; [self.searchBar setShowsCancelButton:NO animated:YES];
if (_passwordsDismissRecognizer) [self reloadSites];
[self.view removeGestureRecognizer:_passwordsDismissRecognizer];
[self reloadPasswords];
[UIView animateWithDuration:0.3f animations:^{ [UIView animateWithDuration:0.3f animations:^{
self.passwordCollectionView.backgroundColor = _backgroundColor; self.collectionView.backgroundColor = [self.collectionView.backgroundColor colorWithAlphaComponent:0];
}]; }];
} }
} }
@ -267,11 +258,11 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchBar == self.passwordsSearchBar) { if (searchBar == self.searchBar) {
if ([[self.query stringByTrimmingCharactersInSet:_siteNameAcceptableCharactersSet] length]) if ([[self.query stringByTrimmingCharactersInSet:self.siteNameAcceptableCharactersSet] length])
[self showTips:MPPasswordsBadNameTip]; [self showTips:MPPasswordsBadNameTip];
[self reloadPasswords]; [self reloadSites];
} }
} }
@ -321,42 +312,42 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
PearlRemoveNotificationObservers(); PearlRemoveNotificationObservers();
PearlAddNotificationObserver( UIApplicationWillResignActiveNotification, nil, [NSOperationQueue mainQueue], PearlAddNotificationObserver( UIApplicationWillResignActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) { ^(MPSitesViewController *self, NSNotification *note) {
[self.view endEditing:YES]; [self.view endEditing:YES];
self.passwordSelectionContainer.visible = NO; self.view.visible = NO;
} ); } );
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue], PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) { ^(MPSitesViewController *self, NSNotification *note) {
[UIView animateWithDuration:0.7f animations:^{ [UIView animateWithDuration:0.7f animations:^{
self.passwordSelectionContainer.visible = YES; self.view.visible = YES;
}]; }];
} ); } );
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue], PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) { ^(MPSitesViewController *self, NSNotification *note) {
[self viewWillAppear:YES]; [self viewWillAppear:YES];
} ); } );
PearlAddNotificationObserver( MPSignedOutNotification, nil, nil, PearlAddNotificationObserver( MPSignedOutNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) { ^(MPSitesViewController *self, NSNotification *note) {
PearlMainQueue( ^{ PearlMainQueue( ^{
self->_fetchedResultsController = nil; self.fetchedResultsController = nil;
self.query = nil; self.query = nil;
} ); } );
} ); } );
PearlAddNotificationObserver( MPCheckConfigNotification, nil, nil, PearlAddNotificationObserver( MPCheckConfigNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) { ^(MPSitesViewController *self, NSNotification *note) {
PearlMainQueue( ^{ PearlMainQueue( ^{
[self updateConfigKey:note.object]; [self updateConfigKey:note.object];
} ); } );
} ); } );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, nil, nil, PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresWillChangeNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) { ^(MPSitesViewController *self, NSNotification *note) {
self->_fetchedResultsController = nil; self.fetchedResultsController = nil;
[self reloadPasswords]; [self reloadSites];
} ); } );
PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, nil, nil, PearlAddNotificationObserver( NSPersistentStoreCoordinatorStoresDidChangeNotification, nil, nil,
^(MPPasswordsViewController *self, NSNotification *note) { ^(MPSitesViewController *self, NSNotification *note) {
PearlMainQueue( ^{ PearlMainQueue( ^{
[self reloadPasswords]; [self reloadSites];
[self registerObservers]; [self registerObservers];
} ); } );
} ); } );
@ -373,12 +364,12 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)updateConfigKey:(NSString *)key { - (void)updateConfigKey:(NSString *)key {
if (!key || [key isEqualToString:NSStringFromSelector( @selector( dictationSearch ) )]) if (!key || [key isEqualToString:NSStringFromSelector( @selector( dictationSearch ) )])
self.passwordsSearchBar.keyboardType = [[MPiOSConfig get].dictationSearch boolValue]? UIKeyboardTypeDefault: UIKeyboardTypeURL; self.searchBar.keyboardType = [[MPiOSConfig get].dictationSearch boolValue]? UIKeyboardTypeDefault: UIKeyboardTypeURL;
if (!key || [key isEqualToString:NSStringFromSelector( @selector( hidePasswords ) )]) if (!key || [key isEqualToString:NSStringFromSelector( @selector( hidePasswords ) )])
[self.passwordCollectionView reloadData]; [self.collectionView reloadData];
} }
- (void)reloadPasswords { - (void)reloadSites {
[self.fetchedResultsController.managedObjectContext performBlock:^{ [self.fetchedResultsController.managedObjectContext performBlock:^{
static NSRegularExpression *fuzzyRE; static NSRegularExpression *fuzzyRE;
@ -395,7 +386,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
[fuzzyGroups addObject:[queryString substringWithRange:result.range]]; [fuzzyGroups addObject:[queryString substringWithRange:result.range]];
}]; }];
_fuzzyGroups = fuzzyGroups; self.fuzzyGroups = fuzzyGroups;
NSError *error = nil; NSError *error = nil;
self.fetchedResultsController.fetchRequest.predicate = self.fetchedResultsController.fetchRequest.predicate =
@ -404,11 +395,11 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
MPError( error, @"Couldn't fetch sites." ); MPError( error, @"Couldn't fetch sites." );
PearlMainQueue( ^{ PearlMainQueue( ^{
[self.passwordCollectionView updateDataSource:_passwordCollectionSections [self.collectionView updateDataSource:self.dataSource
toSections:[self createPasswordCollectionSections] toSections:[self createPasswordCollectionSections]
reloadItems:@[ MPTransientPasswordItem ] completion:^(BOOL finished) { reloadItems:@[ MPTransientPasswordItem ] completion:^(BOOL finished) {
for (MPPasswordCell *cell in self.passwordCollectionView.visibleCells) for (MPSiteCell *cell in self.collectionView.visibleCells)
[cell setFuzzyGroups:_fuzzyGroups]; [cell setFuzzyGroups:self.fuzzyGroups];
}]; }];
} ); } );
}]; }];
@ -418,33 +409,33 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (NSString *)query { - (NSString *)query {
return [self.passwordsSearchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; return [self.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
} }
- (void)setQuery:(NSString *)query { - (void)setQuery:(NSString *)query {
self.passwordsSearchBar.text = [query stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; self.searchBar.text = [query stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[self reloadPasswords]; [self reloadSites];
} }
- (NSFetchedResultsController *)fetchedResultsController { - (NSFetchedResultsController *)fetchedResultsController {
if (!_fetchedResultsController) { if (!self.fetchedResultsController) {
[MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) { [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )]; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
fetchRequest.sortDescriptors = @[ fetchRequest.sortDescriptors = @[
[[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO] [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO]
]; ];
fetchRequest.fetchBatchSize = 10; fetchRequest.fetchBatchSize = 10;
_fetchedResultsController = self.fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:mainContext [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:mainContext
sectionNameKeyPath:nil cacheName:nil]; sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self; self.fetchedResultsController.delegate = self;
}]; }];
[self registerObservers]; [self registerObservers];
} }
return _fetchedResultsController; return self.fetchedResultsController;
} }
- (void)setActive:(BOOL)active { - (void)setActive:(BOOL)active {
@ -458,7 +449,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
[UIView animateWithDuration:animated? 0.4f: 0 animations:^{ [UIView animateWithDuration:animated? 0.4f: 0 animations:^{
[self.navigationBarToTopConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh]; [self.navigationBarToTopConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh];
[self.passwordsToBottomConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh]; [self.sitesToBottomConstraint updatePriority:active? 1: UILayoutPriorityDefaultHigh];
[self.view layoutIfNeeded]; [self.view layoutIfNeeded];
} completion:completion]; } completion:completion];
} }
@ -467,8 +458,8 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (IBAction)dismissPopdown:(id)sender { - (IBAction)dismissPopdown:(id)sender {
if (_popdownVC) if (self.popdownVC)
[[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:_popdownVC destination:self] perform]; [[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:self.popdownVC destination:self] perform];
else else
self.popdownToTopConstraint.priority = UILayoutPriorityDefaultHigh; self.popdownToTopConstraint.priority = UILayoutPriorityDefaultHigh;
} }

View File

@ -20,7 +20,7 @@
#import "MPiOSAppDelegate.h" #import "MPiOSAppDelegate.h"
#import "UIColor+Expanded.h" #import "UIColor+Expanded.h"
#import "MPAppDelegate_InApp.h" #import "MPAppDelegate_InApp.h"
#import "MPPasswordsViewController.h" #import "MPSitesViewController.h"
PearlEnum( MPDevelopmentFuelConsumption, PearlEnum( MPDevelopmentFuelConsumption,
MPDevelopmentFuelConsumptionQuarterly, MPDevelopmentFuelConsumptionMonthly, MPDevelopmentFuelWeekly ); MPDevelopmentFuelConsumptionQuarterly, MPDevelopmentFuelConsumptionMonthly, MPDevelopmentFuelWeekly );
@ -191,11 +191,11 @@ PearlEnum( MPDevelopmentFuelConsumption,
#pragma mark - Private #pragma mark - Private
- (MPPasswordsViewController *)dismissPopup { - (MPSitesViewController *)dismissPopup {
for (UIViewController *vc = self; (vc = vc.parentViewController);) for (UIViewController *vc = self; (vc = vc.parentViewController);)
if ([vc isKindOfClass:[MPPasswordsViewController class]]) { if ([vc isKindOfClass:[MPSitesViewController class]]) {
MPPasswordsViewController *passwordsVC = (MPPasswordsViewController *)vc; MPSitesViewController *passwordsVC = (MPSitesViewController *)vc;
[passwordsVC dismissPopdown:self]; [passwordsVC dismissPopdown:self];
return passwordsVC; return passwordsVC;
} }

View File

@ -54,19 +54,19 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
@property(nonatomic, strong) NSTimer *marqueeTipTimer; @property(nonatomic, strong) NSTimer *marqueeTipTimer;
@property(nonatomic, strong) NSArray *marqueeTipTexts; @property(nonatomic, strong) NSArray *marqueeTipTexts;
@property(nonatomic) NSUInteger marqueeTipTextIndex; @property(nonatomic) NSUInteger marqueeTipTextIndex;
@property(nonatomic, copy) NSString *masterPasswordChoice;
@property(nonatomic, strong) NSOperationQueue *afterUpdates;
@property(nonatomic, weak) id contextChangedObserver;
@end @end
@implementation MPUsersViewController { @implementation MPUsersViewController
NSString *_masterPasswordChoice;
NSOperationQueue *_afterUpdates;
__weak id _contextChangedObserver;
}
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
_afterUpdates = [NSOperationQueue new]; self.afterUpdates = [NSOperationQueue new];
self.marqueeTipTexts = @[ self.marqueeTipTexts = @[
strl( @"Thanks, lhunath ➚" ), strl( @"Thanks, lhunath ➚" ),
@ -205,7 +205,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
return NO; return NO;
} }
if (![masterPassword isEqualToString:_masterPasswordChoice]) { if (![masterPassword isEqualToString:self.masterPasswordChoice]) {
// Master password confirmation failed. // Master password confirmation failed.
[self showEntryTip:strl( @"Looks like a typo!\nTry again; enter your master password twice." )]; [self showEntryTip:strl( @"Looks like a typo!\nTry again; enter your master password twice." )];
self.activeUserState = MPActiveUserStateMasterPasswordChoice; self.activeUserState = MPActiveUserStateMasterPasswordChoice;
@ -655,7 +655,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
- (void)afterUpdatesMainQueue:(void ( ^ )(void))block { - (void)afterUpdatesMainQueue:(void ( ^ )(void))block {
[_afterUpdates addOperationWithBlock:^{ [self.afterUpdates addOperationWithBlock:^{
PearlMainQueue( block ); PearlMainQueue( block );
}]; }];
} }
@ -664,15 +664,15 @@ referenceSizeForFooterInSection:(NSInteger)section {
[self removeKeyPathObservers]; [self removeKeyPathObservers];
PearlRemoveNotificationObservers(); PearlRemoveNotificationObservers();
[[NSNotificationCenter defaultCenter] removeObserver:_contextChangedObserver]; [[NSNotificationCenter defaultCenter] removeObserver:self.contextChangedObserver];
} }
- (void)registerObservers { - (void)registerObservers {
[self removeObservers]; [self removeObservers];
[self observeKeyPath:@"avatarCollectionView.contentOffset" withBlock: [self observeKeyPath:@"avatarCollectionView.contentOffset" withBlock:
^(id from, id to, NSKeyValueChange cause, MPUsersViewController *_self) { ^(id from, id to, NSKeyValueChange cause, MPUsersViewController *self) {
[_self updateAvatarVisibility]; [self updateAvatarVisibility];
}]; }];
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue], PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
@ -696,7 +696,8 @@ referenceSizeForFooterInSection:(NSInteger)section {
[self.keyboardHeightConstraint updateConstant:keyboardHeight]; [self.keyboardHeightConstraint updateConstant:keyboardHeight];
} ); } );
if ((_contextChangedObserver = [MPiOSAppDelegate managedObjectContextChanged:^(NSDictionary<NSManagedObjectID *, NSString *> *affectedObjects) { if ((self.contextChangedObserver
= [MPiOSAppDelegate managedObjectContextChanged:^(NSDictionary<NSManagedObjectID *, NSString *> *affectedObjects) {
if ([[[affectedObjects allKeys] filteredArrayUsingPredicate: if ([[[affectedObjects allKeys] filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(NSManagedObjectID *objectID, NSDictionary *bindings) { [NSPredicate predicateWithBlock:^BOOL(NSManagedObjectID *objectID, NSDictionary *bindings) {
return [objectID.entity.name isEqualToString:NSStringFromClass( [MPUserEntity class] )]; return [objectID.entity.name isEqualToString:NSStringFromClass( [MPUserEntity class] )];
@ -772,7 +773,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
isNew:&isNew].permanentObjectID; isNew:&isNew].permanentObjectID;
[self.avatarCollectionView reloadData]; [self.avatarCollectionView reloadData];
NSUInteger selectedAvatarItem = isNew? [_userIDs count]: selectUserID? [_userIDs indexOfObject:selectUserID]: NSNotFound; NSUInteger selectedAvatarItem = isNew? [self.userIDs count]: selectUserID? [self.userIDs indexOfObject:selectUserID]: NSNotFound;
if (selectedAvatarItem != NSNotFound) if (selectedAvatarItem != NSNotFound)
[self.avatarCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:selectedAvatarItem inSection:0] animated:NO [self.avatarCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:selectedAvatarItem inSection:0] animated:NO
scrollPosition:UICollectionViewScrollPositionCenteredHorizontally]; scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
@ -791,7 +792,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
- (void)setActiveUserState:(MPActiveUserState)activeUserState animated:(BOOL)animated { - (void)setActiveUserState:(MPActiveUserState)activeUserState animated:(BOOL)animated {
_activeUserState = activeUserState; _activeUserState = activeUserState;
_masterPasswordChoice = nil; self.masterPasswordChoice = nil;
if (activeUserState != MPActiveUserStateMinimized && (!self.active || [MPiOSAppDelegate get].activeUserOID)) { if (activeUserState != MPActiveUserStateMinimized && (!self.active || [MPiOSAppDelegate get].activeUserOID)) {
[[MPiOSAppDelegate get] signOutAnimated:YES]; [[MPiOSAppDelegate get] signOutAnimated:YES];
@ -799,7 +800,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
} }
// Set the entry container's contents. // Set the entry container's contents.
[_afterUpdates setSuspended:YES]; [self.afterUpdates setSuspended:YES];
__block BOOL requestFirstResponder = NO; __block BOOL requestFirstResponder = NO;
[self.view layoutIfNeeded]; [self.view layoutIfNeeded];
[UIView animateWithDuration:animated? 0.4f: 0 animations:^{ [UIView animateWithDuration:animated? 0.4f: 0 animations:^{
@ -828,7 +829,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
break; break;
} }
case MPActiveUserStateMasterPasswordConfirmation: { case MPActiveUserStateMasterPasswordConfirmation: {
_masterPasswordChoice = self.entryField.text; self.masterPasswordChoice = self.entryField.text;
self.entryLabel.text = strl( @"Confirm your master password:" ); self.entryLabel.text = strl( @"Confirm your master password:" );
self.entryField.secureTextEntry = YES; self.entryField.secureTextEntry = YES;
self.entryField.autocapitalizationType = UITextAutocapitalizationTypeNone; self.entryField.autocapitalizationType = UITextAutocapitalizationTypeNone;
@ -890,7 +891,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
[self.view layoutIfNeeded]; [self.view layoutIfNeeded];
} completion:^(BOOL finished) { } completion:^(BOOL finished) {
[_afterUpdates setSuspended:NO]; [self.afterUpdates setSuspended:NO];
}]; }];
[self.entryField resignFirstResponder]; [self.entryField resignFirstResponder];

View File

@ -1,20 +1,20 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// NSString(MPMarkDown).h // Master Password is free software: you can redistribute it and/or modify
// NSString(MPMarkDown) // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by lhunath on 2014-09-28. // Master Password is distributed in the hope that it will be useful,
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>

View File

@ -1,20 +1,20 @@
/** //==============================================================================
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com) // This file is part of Master Password.
* // Copyright (c) 2011-2017, Maarten Billemont.
* See the enclosed file LICENSE for license information (LGPLv3). If you did
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
*
* @author Maarten Billemont <lhunath@lyndir.com>
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
*/
// //
// NSString(MPMarkDown).h // Master Password is free software: you can redistribute it and/or modify
// NSString(MPMarkDown) // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// //
// Created by lhunath on 2014-09-28. // Master Password is distributed in the hope that it will be useful,
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved. // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================
#import "NSString+MPMarkDown.h" #import "NSString+MPMarkDown.h"
#import "markdown_lib.h" #import "markdown_lib.h"

View File

@ -4,7 +4,6 @@
<adaptation id="fullscreen"/> <adaptation id="fullscreen"/>
</device> </device>
<dependencies> <dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/> <capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/> <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
@ -104,7 +103,7 @@
</constraints> </constraints>
</imageView> </imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
<rect key="frame" x="43.5" y="263" width="128.5" height="16"/> <rect key="frame" x="44" y="263" width="128.5" height="16"/>
<subviews> <subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
<rect key="frame" x="5" y="0.0" width="118.5" height="16"/> <rect key="frame" x="5" y="0.0" width="118.5" height="16"/>
@ -589,7 +588,7 @@
<nil key="simulatedTopBarMetrics"/> <nil key="simulatedTopBarMetrics"/>
<connections> <connections>
<segue destination="osn-5H-SWW" kind="custom" identifier="emergency" customClass="MPOverlaySegue" id="gtX-Cx-AA2"/> <segue destination="osn-5H-SWW" kind="custom" identifier="emergency" customClass="MPOverlaySegue" id="gtX-Cx-AA2"/>
<segue destination="nkY-z6-8jd" kind="custom" identifier="passwords" customClass="MPPasswordsSegue" id="Ozp-YT-Utx"/> <segue destination="nkY-z6-8jd" kind="custom" identifier="passwords" customClass="MPSitesSegue" id="Ozp-YT-Utx"/>
<segue destination="S8q-YF-Kt9" kind="custom" identifier="users" customClass="MPRootSegue" id="StK-nr-nps"/> <segue destination="S8q-YF-Kt9" kind="custom" identifier="users" customClass="MPRootSegue" id="StK-nr-nps"/>
</connections> </connections>
</viewController> </viewController>
@ -1125,7 +1124,7 @@
<outlet property="feedbackCell" destination="9QG-lM-ymM" id="18X-Ph-0ac"/> <outlet property="feedbackCell" destination="9QG-lM-ymM" id="18X-Ph-0ac"/>
<outlet property="generated1TypeControl" destination="E0r-Ey-eVH" id="w47-Md-FAy"/> <outlet property="generated1TypeControl" destination="E0r-Ey-eVH" id="w47-Md-FAy"/>
<outlet property="generated2TypeControl" destination="H8F-E0-dqF" id="t7o-RI-Sgq"/> <outlet property="generated2TypeControl" destination="H8F-E0-dqF" id="t7o-RI-Sgq"/>
<outlet property="passwordTypeExample" destination="lhS-L1-2OB" id="Q3B-ey-VM6"/> <outlet property="typeSamplePassword" destination="lhS-L1-2OB" id="Q3B-ey-VM6"/>
<outlet property="savePasswordSwitch" destination="Jr5-mX-nw0" id="eqq-Xo-9Iq"/> <outlet property="savePasswordSwitch" destination="Jr5-mX-nw0" id="eqq-Xo-9Iq"/>
<outlet property="showHelpCell" destination="eth-Dc-JYn" id="0Tq-I3-SwK"/> <outlet property="showHelpCell" destination="eth-Dc-JYn" id="0Tq-I3-SwK"/>
<outlet property="signOutCell" destination="R30-AU-bR6" id="Sam-x5-p3H"/> <outlet property="signOutCell" destination="R30-AU-bR6" id="Sam-x5-p3H"/>
@ -1137,20 +1136,17 @@
</objects> </objects>
<point key="canvasLocation" x="2624.5" y="2175.5"/> <point key="canvasLocation" x="2624.5" y="2175.5"/>
</scene> </scene>
<!--Passwords View Controller--> <!--Sites View Controller-->
<scene sceneID="I40-Es-1gK"> <scene sceneID="I40-Es-1gK">
<objects> <objects>
<viewController id="nkY-z6-8jd" customClass="MPPasswordsViewController" sceneMemberID="viewController"> <viewController id="nkY-z6-8jd" customClass="MPSitesViewController" sceneMemberID="viewController">
<layoutGuides> <layoutGuides>
<viewControllerLayoutGuide type="top" id="S9X-2T-e1e"/> <viewControllerLayoutGuide type="top" id="S9X-2T-e1e"/>
<viewControllerLayoutGuide type="bottom" id="c12-XI-Rv9"/> <viewControllerLayoutGuide type="bottom" id="c12-XI-Rv9"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="MSX-uI-cwS" userLabel="Root"> <view key="view" contentMode="scaleToFill" id="tI8-OT-LrO">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tI8-OT-LrO" userLabel="Passwords Root">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K2e-Gh-7hH" userLabel="Passwords Container"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K2e-Gh-7hH" userLabel="Passwords Container">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
@ -1165,7 +1161,7 @@
<inset key="sectionInset" minX="10" minY="200" maxX="10" maxY="10"/> <inset key="sectionInset" minX="10" minY="200" maxX="10" maxY="10"/>
</collectionViewFlowLayout> </collectionViewFlowLayout>
<cells> <cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPPasswordCell" id="W2g-yv-V3V" customClass="MPPasswordCell"> <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="MPSiteCell" id="W2g-yv-V3V" customClass="MPSiteCell">
<rect key="frame" x="10" y="200" width="355" height="100"/> <rect key="frame" x="10" y="200" width="355" height="100"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center"> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
@ -1625,7 +1621,7 @@
</connections> </connections>
</searchBar> </searchBar>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip"> <view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip">
<rect key="frame" x="37.5" y="86" width="300.5" height="75.5"/> <rect key="frame" x="38" y="86" width="300.5" height="75.5"/>
<subviews> <subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="Rt5-v4-I0R"> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="Rt5-v4-I0R">
<rect key="frame" x="0.0" y="0.0" width="300.5" height="75.5"/> <rect key="frame" x="0.0" y="0.0" width="300.5" height="75.5"/>
@ -1697,7 +1693,7 @@ eg. apple.com, rmitchell@twitter.com</string>
</constraints> </constraints>
</view> </view>
</subviews> </subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.1215686275" green="0.12941176469999999" blue="0.14117647059999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstAttribute="trailing" secondItem="uuT-jm-2La" secondAttribute="trailing" id="2Ep-4f-05N"/> <constraint firstAttribute="trailing" secondItem="uuT-jm-2La" secondAttribute="trailing" id="2Ep-4f-05N"/>
<constraint firstAttribute="top" secondItem="aGs-1S-aC3" secondAttribute="bottom" priority="1" id="48O-MN-C75"/> <constraint firstAttribute="top" secondItem="aGs-1S-aC3" secondAttribute="bottom" priority="1" id="48O-MN-C75"/>
@ -1705,6 +1701,7 @@ eg. apple.com, rmitchell@twitter.com</string>
<constraint firstItem="uuT-jm-2La" firstAttribute="leading" secondItem="tI8-OT-LrO" secondAttribute="leading" id="DJd-kO-WGu"/> <constraint firstItem="uuT-jm-2La" firstAttribute="leading" secondItem="tI8-OT-LrO" secondAttribute="leading" id="DJd-kO-WGu"/>
<constraint firstItem="aGs-1S-aC3" firstAttribute="leading" secondItem="tI8-OT-LrO" secondAttribute="leading" id="Etb-tB-Svy"/> <constraint firstItem="aGs-1S-aC3" firstAttribute="leading" secondItem="tI8-OT-LrO" secondAttribute="leading" id="Etb-tB-Svy"/>
<constraint firstItem="uuT-jm-2La" firstAttribute="top" secondItem="tI8-OT-LrO" secondAttribute="top" priority="500" id="Evy-zY-OaB"/> <constraint firstItem="uuT-jm-2La" firstAttribute="top" secondItem="tI8-OT-LrO" secondAttribute="top" priority="500" id="Evy-zY-OaB"/>
<constraint firstItem="uuT-jm-2La" firstAttribute="bottom" secondItem="S9X-2T-e1e" secondAttribute="bottom" priority="500" constant="44" id="HAi-jL-BdJ"/>
<constraint firstAttribute="trailing" secondItem="K2e-Gh-7hH" secondAttribute="trailing" id="Hnk-mU-GSd"/> <constraint firstAttribute="trailing" secondItem="K2e-Gh-7hH" secondAttribute="trailing" id="Hnk-mU-GSd"/>
<constraint firstItem="aGs-1S-aC3" firstAttribute="trailing" secondItem="c9g-Sg-lz3" secondAttribute="trailing" id="KIJ-IE-Snm"/> <constraint firstItem="aGs-1S-aC3" firstAttribute="trailing" secondItem="c9g-Sg-lz3" secondAttribute="trailing" id="KIJ-IE-Snm"/>
<constraint firstItem="XNM-XQ-rMe" firstAttribute="height" secondItem="tI8-OT-LrO" secondAttribute="height" id="OCp-tF-gVL"/> <constraint firstItem="XNM-XQ-rMe" firstAttribute="height" secondItem="tI8-OT-LrO" secondAttribute="height" id="OCp-tF-gVL"/>
@ -1728,27 +1725,13 @@ eg. apple.com, rmitchell@twitter.com</string>
<userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/> <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</view> </view>
</subviews>
<color key="backgroundColor" red="0.1215686275" green="0.12941176469999999" blue="0.14117647059999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="tI8-OT-LrO" firstAttribute="leading" secondItem="MSX-uI-cwS" secondAttribute="leading" id="3au-dn-EZA"/>
<constraint firstItem="uuT-jm-2La" firstAttribute="bottom" secondItem="S9X-2T-e1e" secondAttribute="bottom" priority="500" constant="44" id="HAi-jL-BdJ"/>
<constraint firstAttribute="top" secondItem="tI8-OT-LrO" secondAttribute="top" id="Vub-z3-GJi"/>
<constraint firstItem="c12-XI-Rv9" firstAttribute="top" secondItem="tI8-OT-LrO" secondAttribute="bottom" id="auY-cK-Gh9"/>
<constraint firstAttribute="trailing" secondItem="tI8-OT-LrO" secondAttribute="trailing" id="cHT-PO-Feh"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
</userDefinedRuntimeAttributes>
</view>
<connections> <connections>
<outlet property="badNameTipContainer" destination="LEX-BK-PdS" id="2lk-fp-Ghc"/> <outlet property="badNameTipContainer" destination="LEX-BK-PdS" id="2lk-fp-Ghc"/>
<outlet property="collectionView" destination="aXw-tn-8Sj" id="fNR-qS-qNP"/>
<outlet property="navigationBar" destination="uuT-jm-2La" id="lRz-Ok-jvw"/> <outlet property="navigationBar" destination="uuT-jm-2La" id="lRz-Ok-jvw"/>
<outlet property="navigationBarToTopConstraint" destination="48O-MN-C75" id="bbn-GO-2Ke"/> <outlet property="navigationBarToTopConstraint" destination="48O-MN-C75" id="bbn-GO-2Ke"/>
<outlet property="passwordCollectionView" destination="aXw-tn-8Sj" id="fNR-qS-qNP"/> <outlet property="searchBar" destination="aGs-1S-aC3" id="iFW-aL-CVu"/>
<outlet property="passwordSelectionContainer" destination="tI8-OT-LrO" id="J91-sd-kq3"/> <outlet property="sitesToBottomConstraint" destination="dNt-uf-8BC" id="Ta6-eL-z7w"/>
<outlet property="passwordsSearchBar" destination="aGs-1S-aC3" id="iFW-aL-CVu"/>
<outlet property="passwordsToBottomConstraint" destination="dNt-uf-8BC" id="Ta6-eL-z7w"/>
<outlet property="popdownContainer" destination="bnY-br-a2v" id="7QN-qY-iCl"/> <outlet property="popdownContainer" destination="bnY-br-a2v" id="7QN-qY-iCl"/>
<outlet property="popdownToTopConstraint" destination="BdD-Kc-eHl" id="59Y-ap-Yn4"/> <outlet property="popdownToTopConstraint" destination="BdD-Kc-eHl" id="59Y-ap-Yn4"/>
<outlet property="popdownView" destination="XNM-XQ-rMe" id="FaW-4m-Fff"/> <outlet property="popdownView" destination="XNM-XQ-rMe" id="FaW-4m-Fff"/>
@ -1780,7 +1763,7 @@ eg. apple.com, rmitchell@twitter.com</string>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1lc-e7-Qme" userLabel="Emergency Generator"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1lc-e7-Qme" userLabel="Emergency Generator">
<rect key="frame" x="20" y="135.5" width="335" height="397.5"/> <rect key="frame" x="20" y="135" width="335" height="397.5"/>
<subviews> <subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Emergency Generator" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="4Lh-s0-Dbt"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Emergency Generator" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="4Lh-s0-Dbt">
<rect key="frame" x="20" y="20" width="295" height="21"/> <rect key="frame" x="20" y="20" width="295" height="21"/>
@ -2578,13 +2561,13 @@ See </string>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Negare non possum" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Pax-1J-IZi"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Negare non possum" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Pax-1J-IZi">
<rect key="frame" x="20" y="226" width="291" height="21"/> <rect key="frame" x="20" y="226" width="291" height="20"/>
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/> <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="749" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ra0-yS-99P"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalCompressionResistancePriority="749" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ra0-yS-99P">
<rect key="frame" x="20" y="255" width="335" height="104.5"/> <rect key="frame" x="20" y="254" width="335" height="105.5"/>
<string key="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. At multis se probavit. Sic consequentibus vestris sublatis prima tolluntur. Nescio quo modo praetervolavit oratio. Reguli reiciendam; Theophrastus mediocriterne delectat, cum tractat locos ab Aristotele ante tractatos? Duo Reges: constructio interrete.</string> <string key="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. At multis se probavit. Sic consequentibus vestris sublatis prima tolluntur. Nescio quo modo praetervolavit oratio. Reguli reiciendam; Theophrastus mediocriterne delectat, cum tractat locos ab Aristotele ante tractatos? Duo Reges: constructio interrete.</string>
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/> <fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -2603,7 +2586,7 @@ See </string>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="$0.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="68f-wn-UlS"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="$0.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="68f-wn-UlS">
<rect key="frame" x="319" y="226" width="36" height="21"/> <rect key="frame" x="319" y="226" width="36" height="20"/>
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/> <fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
<color key="textColor" red="0.47450980390000003" green="0.86666666670000003" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.47450980390000003" green="0.86666666670000003" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -2860,13 +2843,13 @@ Invested: 3.7 work hours</string>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="hok petwuvaqu xixo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="GfC-j4-Qx7" userLabel="Answer Field"> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="hok petwuvaqu xixo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="GfC-j4-Qx7" userLabel="Answer Field">
<rect key="frame" x="8" y="48" width="359" height="41.5"/> <rect key="frame" x="8" y="48" width="359" height="42"/>
<color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/> <fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/> <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/>
</textField> </textField>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="Use this as the answer for each security question on this site." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EUe-A5-H8h"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="Use this as the answer for each security question on this site." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EUe-A5-H8h">
<rect key="frame" x="8" y="97.5" width="359" height="14.5"/> <rect key="frame" x="8" y="98" width="359" height="14"/>
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/> <fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -2944,7 +2927,7 @@ Invested: 3.7 work hours</string>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="mother" textAlignment="center" minimumFontSize="14" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="T2F-PD-Nw8" userLabel="Question Field"> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="mother" textAlignment="center" minimumFontSize="14" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="T2F-PD-Nw8" userLabel="Question Field">
<rect key="frame" x="8" y="17.5" width="359" height="30"/> <rect key="frame" x="8" y="18" width="359" height="30"/>
<color key="backgroundColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="28"/> <fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="28"/>
@ -2961,7 +2944,7 @@ Invested: 3.7 work hours</string>
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/> <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/>
</textField> </textField>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Enter the single most significant word in the question above." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qqg-Ny-7Po"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Enter the single most significant word in the question above." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qqg-Ny-7Po">
<rect key="frame" x="8" y="55.5" width="359" height="14.5"/> <rect key="frame" x="8" y="56" width="359" height="14"/>
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/> <fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -3123,11 +3106,11 @@ You can temporarily reveal a password by holding your finger down on the site's
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="aNU-Nq-clY"> <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="aNU-Nq-clY">
<rect key="frame" x="0.0" y="341.5" width="375" height="325.5"/> <rect key="frame" x="0.0" y="342.5" width="375" height="324.5"/>
<items/> <items/>
</toolbar> </toolbar>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Lorem ipsum dolor sit amet." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Qi-GN-vhQ" userLabel="Title Label"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Lorem ipsum dolor sit amet." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Qi-GN-vhQ" userLabel="Title Label">
<rect key="frame" x="16" y="361.5" width="343" height="21"/> <rect key="frame" x="16" y="362.5" width="343" height="20"/>
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/> <fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>