From ca9cbc9fd1944302620e1a3bc34653e35100ce01 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Sun, 26 Aug 2012 17:40:32 +0200 Subject: [PATCH] Follow on social networks. [UPDATED] Migrated from MFMailComposeViewController to PearlEMail. [ADDED] Social network "follow" button. --- External/Pearl | 2 +- MasterPassword-iOS.xcodeproj/project.pbxproj | 15 +- MasterPassword/iOS/MPAppDelegate.h | 3 +- MasterPassword/iOS/MPAppDelegate.m | 171 ++++++++++-------- MasterPassword/iOS/MPMainViewController.h | 2 +- MasterPassword/iOS/MPMainViewController.m | 60 +----- MasterPassword/iOS/MPUnlockViewController.h | 2 + MasterPassword/iOS/MPUnlockViewController.m | 62 +++++++ .../iOS/MainStoryboard_iPhone.storyboard | 32 ++++ 9 files changed, 211 insertions(+), 138 deletions(-) diff --git a/External/Pearl b/External/Pearl index 19a70544..50ec656f 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit 19a7054441049ea1519fe0bb72bc52d4542964cc +Subproject commit 50ec656f29ff83de4f5119cf74935f7c8b2c3e38 diff --git a/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword-iOS.xcodeproj/project.pbxproj index 10468019..08580d87 100644 --- a/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -8,8 +8,10 @@ /* Begin PBXBuildFile section */ 93D390BC6AE7A1C9B91A3668 /* MPKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E81EFABC6085AC8AE69 /* MPKey.m */; }; + 93D39262A8A97DB748213309 /* PearlEMail.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D393BB973253D4BAAC84AA /* PearlEMail.m */; }; 93D392B30CE6C58A9A905E0A /* MPAlgorithmV0.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3938863322199C3E7E2E3 /* MPAlgorithmV0.m */; }; 93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */; }; + 93D3932889B6B4206E66A6D6 /* PearlEMail.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */; }; 93D394744B5485303B326ECB /* MPAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B0DF5E3C56355186738 /* MPAlgorithm.m */; }; 93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; }; 93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; }; @@ -89,7 +91,6 @@ DA5587EF15E83C3200860B4F /* social-twitter.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5587E915E83C3200860B4F /* social-twitter.png */; }; DA5587F015E83C3200860B4F /* social-twitter@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5587EA15E83C3200860B4F /* social-twitter@2x.png */; }; DA5587F415E8418200860B4F /* iTunesArtwork-Rounded-73@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5587F115E8418200860B4F /* iTunesArtwork-Rounded-73@2x.png */; }; - DA5587F515E8418200860B4F /* iTunesArtwork-Rounded-256.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5587F215E8418200860B4F /* iTunesArtwork-Rounded-256.png */; }; DA5587F615E8418200860B4F /* iTunesArtwork-Rounded.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5587F315E8418200860B4F /* iTunesArtwork-Rounded.png */; }; DA55888415E8C0BA00860B4F /* google_plus_share.png in Resources */ = {isa = PBXBuildFile; fileRef = DA55887C15E8C0BA00860B4F /* google_plus_share.png */; }; DA55888515E8C0BA00860B4F /* google_plus_share@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA55887D15E8C0BA00860B4F /* google_plus_share@2x.png */; }; @@ -965,6 +966,7 @@ 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = ""; }; 93D3938863322199C3E7E2E3 /* MPAlgorithmV0.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV0.m; sourceTree = ""; }; 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = ""; }; + 93D393BB973253D4BAAC84AA /* PearlEMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlEMail.m; sourceTree = ""; }; 93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; }; 93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = ""; }; 93D398E394E311C545E0A057 /* MPAlgorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithm.h; sourceTree = ""; }; @@ -975,6 +977,7 @@ 93D39D0EF77FEC36EA0FB334 /* MPAlgorithmV1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV1.h; sourceTree = ""; }; 93D39E81EFABC6085AC8AE69 /* MPKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPKey.m; sourceTree = ""; }; 93D39E9D7B9005211E7D5262 /* MPAlgorithmV1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV1.m; sourceTree = ""; }; + 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = ""; }; DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; DA0A1D0315690A9A0092735D /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/Default.png; sourceTree = SOURCE_ROOT; }; DA0A1D0415690A9A0092735D /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/Default@2x.png"; sourceTree = SOURCE_ROOT; }; @@ -1124,7 +1127,6 @@ DA5587E915E83C3200860B4F /* social-twitter.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "social-twitter.png"; sourceTree = ""; }; DA5587EA15E83C3200860B4F /* social-twitter@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "social-twitter@2x.png"; sourceTree = ""; }; DA5587F115E8418200860B4F /* iTunesArtwork-Rounded-73@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iTunesArtwork-Rounded-73@2x.png"; sourceTree = ""; }; - DA5587F215E8418200860B4F /* iTunesArtwork-Rounded-256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iTunesArtwork-Rounded-256.png"; sourceTree = ""; }; DA5587F315E8418200860B4F /* iTunesArtwork-Rounded.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iTunesArtwork-Rounded.png"; sourceTree = ""; }; DA5587F815E8B7B200860B4F /* GooglePlusShare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusShare.h; sourceTree = ""; }; DA5587F915E8B7B200860B4F /* GooglePlusSignIn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusSignIn.h; sourceTree = ""; }; @@ -2603,8 +2605,8 @@ DAB8D46F15036BF600CED3BC /* Resources */ = { isa = PBXGroup; children = ( + DA55873E15E81D9E00860B4F /* iTunesArtwork-Rounded-73.png */, DA5587F115E8418200860B4F /* iTunesArtwork-Rounded-73@2x.png */, - DA5587F215E8418200860B4F /* iTunesArtwork-Rounded-256.png */, DA5587F315E8418200860B4F /* iTunesArtwork-Rounded.png */, DA5587E515E83C3200860B4F /* social-facebook.png */, DA5587E615E83C3200860B4F /* social-facebook@2x.png */, @@ -2612,7 +2614,6 @@ DA5587E815E83C3200860B4F /* social-google+@2x.png */, DA5587E915E83C3200860B4F /* social-twitter.png */, DA5587EA15E83C3200860B4F /* social-twitter@2x.png */, - DA55873E15E81D9E00860B4F /* iTunesArtwork-Rounded-73.png */, DAC4149115C53C48007A716E /* dictionary.lst */, DA902BD01576CA4A00C38161 /* keypad.png */, DA902B931576C0FB00C38161 /* Avatars */, @@ -3524,6 +3525,8 @@ DAFE460715039823003ABA7C /* Pearl-UIKit */ = { isa = PBXGroup; children = ( + 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */, + 93D393BB973253D4BAAC84AA /* PearlEMail.m */, DAFE4A63150399FF003ABA8F /* UIScrollView+PearlFlashingIndicators.h */, DAFE4A63150399FF003ABA8D /* UIScrollView+PearlFlashingIndicators.m */, DAFE4A63150399FF003ABA8B /* UIControl+PearlSelect.h */, @@ -3685,6 +3688,7 @@ DAFE4A63150399FF003ABA94 /* NSDateFormatter+RFC3339.h in Headers */, 93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */, 93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */, + 93D3932889B6B4206E66A6D6 /* PearlEMail.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4608,7 +4612,6 @@ DA5587EF15E83C3200860B4F /* social-twitter.png in Resources */, DA5587F015E83C3200860B4F /* social-twitter@2x.png in Resources */, DA5587F415E8418200860B4F /* iTunesArtwork-Rounded-73@2x.png in Resources */, - DA5587F515E8418200860B4F /* iTunesArtwork-Rounded-256.png in Resources */, DA5587F615E8418200860B4F /* iTunesArtwork-Rounded.png in Resources */, DA55888415E8C0BA00860B4F /* google_plus_share.png in Resources */, DA55888515E8C0BA00860B4F /* google_plus_share@2x.png in Resources */, @@ -4864,6 +4867,7 @@ DAFE4A63150399FF003ABA92 /* NSDateFormatter+RFC3339.m in Sources */, 93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */, 93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */, + 93D39262A8A97DB748213309 /* PearlEMail.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5557,6 +5561,7 @@ DA497BA315E8C90E00B52167 /* AppStore */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = AdHoc; }; DA5BFA3E147E415C00F98B1E /* Build configuration list for PBXProject "MasterPassword-iOS" */ = { isa = XCConfigurationList; diff --git a/MasterPassword/iOS/MPAppDelegate.h b/MasterPassword/iOS/MPAppDelegate.h index 90064a19..032aec33 100644 --- a/MasterPassword/iOS/MPAppDelegate.h +++ b/MasterPassword/iOS/MPAppDelegate.h @@ -10,12 +10,13 @@ #import #import "MPAppDelegate_Shared.h" -@interface MPAppDelegate : MPAppDelegate_Shared +@interface MPAppDelegate : MPAppDelegate_Shared + (MPAppDelegate *)get; - (void)checkConfig; - (void)showGuide; +- (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController; - (void)export; - (void)changeMasterPasswordFor:(MPUserEntity *)user didResetBlock:(void(^)(void))didReset; diff --git a/MasterPassword/iOS/MPAppDelegate.m b/MasterPassword/iOS/MPAppDelegate.m index 8ab7e197..81828d46 100644 --- a/MasterPassword/iOS/MPAppDelegate.m +++ b/MasterPassword/iOS/MPAppDelegate.m @@ -120,8 +120,10 @@ [[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) { if (message.level >= PearlLogLevelWarn) [[LocalyticsSession sharedLocalyticsSession] tagEvent:@"Problem" - attributes:@{@"level": @(PearlLogLevelStr(message.level)), - @"message": message.message}]; + attributes:@{ + @"level": @(PearlLogLevelStr(message.level)), + @"message": message.message + }]; return YES; }]; @@ -135,10 +137,12 @@ [[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault]; [[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsLandscapePhone]; [[UINavigationBar appearance] setTitleTextAttributes: - @{UITextAttributeTextColor: [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f], - UITextAttributeTextShadowColor: [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.8f], - UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0, -1)], - UITextAttributeFont: [UIFont fontWithName:@"Exo-Bold" size:20.0f]}]; + @{ + UITextAttributeTextColor: [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f], + UITextAttributeTextShadowColor: [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.8f], + UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0, -1)], + UITextAttributeFont: [UIFont fontWithName:@"Exo-Bold" size:20.0f] + }]; UIImage *navBarButton = [[UIImage imageNamed:@"ui_navbar_button"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)]; UIImage *navBarBack = [[UIImage imageNamed:@"ui_navbar_back"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)]; @@ -147,10 +151,12 @@ [[UIBarButtonItem appearance] setBackButtonBackgroundImage:navBarBack forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone]; [[UIBarButtonItem appearance] setTitleTextAttributes: - @{UITextAttributeTextColor: [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f], - UITextAttributeTextShadowColor: [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f], - UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0, 1)], - UITextAttributeFont: [UIFont fontWithName:@"HelveticaNeue" size:0.0f]} + @{ + UITextAttributeTextColor: [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f], + UITextAttributeTextShadowColor: [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f], + UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0, 1)], + UITextAttributeFont: [UIFont fontWithName:@"HelveticaNeue" size:0.0f] + } forState:UIControlStateNormal]; UIImage *toolBarImage = [[UIImage imageNamed:@"ui_toolbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(25, 5, 5, 5)]; @@ -236,15 +242,15 @@ if (!importedSitesData) return; - PearlAlert *activityAlert = [PearlAlert showAlertWithTitle:@"Importing" message:@"\n\n" - viewStyle:UIAlertViewStyleDefault initAlert: + PearlAlert *activityAlert = [PearlAlert showAlertWithTitle:@"Importing" message:@"\n\n" + viewStyle:UIAlertViewStyleDefault initAlert: ^(UIAlertView *alert, UITextField *firstField) { UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; activityIndicator.center = CGPointMake(140, 90); [activityIndicator startAnimating]; [alert addSubview:activityIndicator]; } - tappedButtonBlock:nil cancelTitle:nil otherTitles:nil]; + tappedButtonBlock:nil cancelTitle:nil otherTitles:nil]; NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding]; MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) { @@ -337,7 +343,7 @@ [TestFlight passCheckpoint:MPCheckpointActivated]; if (FBSession.activeSession.state == FBSessionStateCreatedOpening) - // An old Facebook Login session that wasn't finished. Clean it up. + // An old Facebook Login session that wasn't finished. Clean it up. [FBSession.activeSession close]; [super applicationDidBecomeActive:application]; @@ -420,25 +426,27 @@ [TestFlight passCheckpoint:MPCheckpointConfig]; [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointConfig attributes: - @{@"rememberLogin": [[MPConfig get].rememberLogin boolValue] - ? @"YES": @"NO", - @"iCloud": [[MPConfig get].iCloud boolValue]? @"YES" - : @"NO", - @"iCloudDecided": [[MPConfig get].iCloudDecided boolValue] - ? @"YES": @"NO", - @"sendInfo": [[MPiOSConfig get].sendInfo boolValue] - ? @"YES": @"NO", - @"helpHidden": [[MPiOSConfig get].helpHidden boolValue] - ? @"YES": @"NO", - @"showQuickStart": [[MPiOSConfig get].showQuickStart boolValue] - ? @"YES": @"NO", - @"firstRun": [[PearlConfig get].firstRun boolValue] - ? @"YES": @"NO", - @"launchCount": [[PearlConfig get].launchCount description], - @"askForReviews": [[PearlConfig get].askForReviews boolValue] - ? @"YES": @"NO", - @"reviewAfterLaunches": [[PearlConfig get].reviewAfterLaunches description], - @"reviewedVersion": [PearlConfig get].reviewedVersion}]; + @{ + @"rememberLogin": [[MPConfig get].rememberLogin boolValue] + ? @"YES": @"NO", + @"iCloud": [[MPConfig get].iCloud boolValue]? @"YES" + : @"NO", + @"iCloudDecided": [[MPConfig get].iCloudDecided boolValue] + ? @"YES": @"NO", + @"sendInfo": [[MPiOSConfig get].sendInfo boolValue] + ? @"YES": @"NO", + @"helpHidden": [[MPiOSConfig get].helpHidden boolValue] + ? @"YES": @"NO", + @"showQuickStart": [[MPiOSConfig get].showQuickStart boolValue] + ? @"YES": @"NO", + @"firstRun": [[PearlConfig get].firstRun boolValue] + ? @"YES": @"NO", + @"launchCount": [[PearlConfig get].launchCount description], + @"askForReviews": [[PearlConfig get].askForReviews boolValue] + ? @"YES": @"NO", + @"reviewAfterLaunches": [[PearlConfig get].reviewAfterLaunches description], + @"reviewedVersion": [PearlConfig get].reviewedVersion + }]; } } @@ -449,6 +457,59 @@ [TestFlight passCheckpoint:MPCheckpointShowGuide]; } +- (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController { + + if (![PearlEMail canSendMail]) + [PearlAlert showAlertWithTitle:@"Feedback" + message: + @"Have a question, comment, issue or just saying thanks?\n\n" + @"We'd love to hear what you think!\n" + @"masterpassword@lyndir.com" + viewStyle:UIAlertViewStyleDefault + initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay + otherTitles:nil]; + + else + if (logs) + [PearlAlert showAlertWithTitle:@"Feedback" + message: + @"Have a question, comment, issue or just saying thanks?\n\n" + @"If you're having trouble, it may help us if you can first reproduce the problem " + @"and then include log files in your message." + viewStyle:UIAlertViewStyleDefault + initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { + [self openFeedbackWithLogs:(buttonIndex_ == [alert_ firstOtherButtonIndex]) forVC:viewController]; + } cancelTitle:nil otherTitles:@"Include Logs", @"No Logs", nil]; + else + [self openFeedbackWithLogs:NO forVC:viewController]; +} + +- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController { + + NSString *userName = [MPAppDelegate get].activeUser.name; + PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug: PearlLogLevelInfo; + + [[[PearlEMail alloc] initForEMailTo:@"Master Password Development " + subject:PearlString(@"Feedback for Master Password [%@]", + [[PearlKeyChain deviceIdentifier] stringByDeletingMatchesOf:@"-.*"]) + body:PearlString(@"\n\n\n" + @"--\n" + @"%@" + @"Master Password %@, build %@", + userName? ([userName stringByAppendingString:@"\n"]): @"", + [PearlInfoPlist get].CFBundleShortVersionString, + [PearlInfoPlist get].CFBundleVersion) + + attachments:logs + ? [[PearlEMailAttachment alloc] initWithContent:[[[PearlLogger get] formatMessagesWithLevel:logLevel] dataUsingEncoding:NSUTF8StringEncoding] + mimeType:@"text/plain" + fileName:PearlString(@"%@-%@.log", + [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]], + [PearlKeyChain deviceIdentifier])] + : nil, nil] + showComposerForVC:viewController]; +} + - (void)export { [PearlAlert showNotice: @@ -476,7 +537,7 @@ - (void)exportShowPasswords:(BOOL)showPasswords { - if (![MFMailComposeViewController canSendMail]) { + if (![PearlEMail canSendMail]) { [PearlAlert showAlertWithTitle:@"Cannot Send Mail" message: @"Your device is not yet set up for sending mail.\n" @@ -511,16 +572,11 @@ NSDateFormatter *exportDateFormatter = [NSDateFormatter new]; [exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"]; - MFMailComposeViewController *composer = [MFMailComposeViewController new]; - [composer setMailComposeDelegate:self]; - [composer setSubject:@"Master Password Export"]; - [composer setMessageBody:message isHTML:NO]; - [composer addAttachmentData: - [exportedSites dataUsingEncoding:NSUTF8StringEncoding] mimeType:@"text/plain" - fileName:PearlString(@"%@ (%@).mpsites", - self.activeUser.name, - [exportDateFormatter stringFromDate:[NSDate date]])]; - [self.window.rootViewController presentModalViewController:composer animated:YES]; + [PearlEMail sendEMailTo:nil subject:@"Master Password Export" body:message + attachments:[[PearlEMailAttachment alloc] initWithContent:[exportedSites dataUsingEncoding:NSUTF8StringEncoding] + mimeType:@"text/plain" fileName: + PearlString(@"%@ (%@).mpsites", self.activeUser.name, [exportDateFormatter stringFromDate:[NSDate date]])], + nil]; } - (void)changeMasterPasswordFor:(MPUserEntity *)user didResetBlock:(void (^)(void))didReset { @@ -557,33 +613,6 @@ [self checkConfig]; } -#pragma mark - MFMailComposeViewControllerDelegate - -- (void)mailComposeController:(MFMailComposeViewController *)controller - didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { - - if (error) - err(@"Error composing mail message: %@", error); - - switch (result) { - case MFMailComposeResultSaved: - case MFMailComposeResultSent: - break; - - case MFMailComposeResultFailed: - [PearlAlert showError:@"A problem occurred while sending the message." - tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { - if (buttonIndex == [alert firstOtherButtonIndex]) - return; - } otherTitles:@"Retry", nil]; - return; - case MFMailComposeResultCancelled: - break; - } - - [controller dismissModalViewControllerAnimated:YES]; -} - #pragma mark - UbiquityStoreManagerDelegate - (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didSwitchToiCloud:(BOOL)iCloudEnabled { diff --git a/MasterPassword/iOS/MPMainViewController.h b/MasterPassword/iOS/MPMainViewController.h index ba5683d8..ea00c524 100644 --- a/MasterPassword/iOS/MPMainViewController.h +++ b/MasterPassword/iOS/MPMainViewController.h @@ -11,7 +11,7 @@ #import "MPElementEntity.h" #import "MPSearchDelegate.h" -@interface MPMainViewController : UIViewController +@interface MPMainViewController : UIViewController @property (assign, nonatomic) BOOL siteInfoHidden; @property (strong, nonatomic) MPElementEntity *activeElement; diff --git a/MasterPassword/iOS/MPMainViewController.m b/MasterPassword/iOS/MPMainViewController.m index 214369f2..7479c4b6 100644 --- a/MasterPassword/iOS/MPMainViewController.m +++ b/MasterPassword/iOS/MPMainViewController.m @@ -713,54 +713,7 @@ #else case 4: { inf(@"Action: Feedback via Mail"); - if (![MFMailComposeViewController canSendMail]) - [PearlAlert showAlertWithTitle:@"Sending Feedback" - message: - @"We'd love to hear what you think!\n\n" - @"Please send any comments or reports to:\n" - @"masterpassword@lyndir.com" - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay - otherTitles:nil]; - - else { - [PearlAlert showAlertWithTitle:@"Sending Feedback" - message: - @"We'd love to hear what you think!\n\n" - @"If you're having trouble, it may help us if you can first reproduce the problem " - @"and then include log files in your message." - viewStyle:UIAlertViewStyleDefault - initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) { - MFMailComposeViewController *composer = [MFMailComposeViewController new]; - [composer setMailComposeDelegate:self]; - [composer setToRecipients:@[@"Master Password Development "]]; - [composer setSubject:PearlString(@"Feedback for Master Password [%@]", - [[PearlKeyChain deviceIdentifier] stringByDeletingMatchesOf:@"-.*"])]; - [composer setMessageBody: - PearlString( - @"\n\n\n" - @"--\n" - @"%@\n" - @"Master Password %@, build %@", - [MPAppDelegate get].activeUser.name, - [PearlInfoPlist get].CFBundleShortVersionString, - [PearlInfoPlist get].CFBundleVersion) - isHTML:NO]; - - if (buttonIndex_ == [alert_ firstOtherButtonIndex]) { - PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug - : PearlLogLevelInfo; - [composer addAttachmentData:[[[PearlLogger get] formatMessagesWithLevel:logLevel] dataUsingEncoding:NSUTF8StringEncoding] - mimeType:@"text/plain" - fileName:PearlString(@"%@-%@.log", - [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]], - [PearlKeyChain deviceIdentifier])]; - } - - [self presentModalViewController:composer animated:YES]; - } - cancelTitle:nil otherTitles:@"Include Logs", @"No Logs", nil]; - } + [[MPAppDelegate get] showFeedbackWithLogs:YES forVC:self]; break; } case 5: @@ -784,17 +737,6 @@ nil]; } -- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result - error:(NSError *)error { - - if (error) - err(@"Feedback composer error: %@, result: %d", error, result); - else - inf(@"Feedback composer result: %d", result); - - [controller dismissViewControllerAnimated:YES completion:nil]; -} - - (MPElementType)selectedType { return self.activeElement.type; diff --git a/MasterPassword/iOS/MPUnlockViewController.h b/MasterPassword/iOS/MPUnlockViewController.h index 3e9ca8ad..789c0382 100644 --- a/MasterPassword/iOS/MPUnlockViewController.h +++ b/MasterPassword/iOS/MPUnlockViewController.h @@ -32,5 +32,7 @@ - (IBAction)facebook:(UIButton *)sender; - (IBAction)twitter:(UIButton *)sender; - (IBAction)google:(UIButton *)sender; +- (IBAction)mail:(UIButton *)sender; +- (IBAction)add:(UIButton *)sender; @end diff --git a/MasterPassword/iOS/MPUnlockViewController.m b/MasterPassword/iOS/MPUnlockViewController.m index f0cc5a6d..904a0d2f 100644 --- a/MasterPassword/iOS/MPUnlockViewController.m +++ b/MasterPassword/iOS/MPUnlockViewController.m @@ -818,6 +818,68 @@ open]; } +- (IBAction)mail:(UIButton *)sender { + + [[MPAppDelegate get] showFeedbackWithLogs:NO forVC:self]; +} + +- (IBAction)add:(UIButton *)sender { + + [PearlSheet showSheetWithTitle:@"Follow Master Password" message:nil viewStyle:UIActionSheetStyleBlackTranslucent + initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { + if (buttonIndex == [sheet cancelButtonIndex]) + return; + + if (buttonIndex == [sheet firstOtherButtonIndex]) { + // Google+ + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://plus.google.com/116256327773442623984/about"]]; + return; + } + if (buttonIndex == [sheet firstOtherButtonIndex] + 1) { + // Facebook + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://www.facebook.com/masterpasswordapp"]]; + return; + } + if (buttonIndex == [sheet firstOtherButtonIndex] + 2) { + // Twitter + UIApplication *application = [UIApplication sharedApplication]; + for (NSString *candidate in @[ + @"twitter://user?screen_name=%@", // Twitter + @"tweetbot:///user_profile/%@", // TweetBot + @"echofon:///user_timeline?%@", // Echofon + @"twit:///user?screen_name=%@", // Twittelator Pro + @"x-seesmic://twitter_profile?twitter_screen_name=%@", // Seesmic + @"x-birdfeed://user?screen_name=%@", // Birdfeed + @"tweetings:///user?screen_name=%@", // Tweetings + @"simplytweet:?link=http://twitter.com/%@", // SimplyTweet + @"icebird://user?screen_name=%@", // IceBird + @"fluttr://user/%@", // Fluttr + @"http://twitter.com/%@"]) { + NSURL *url = [NSURL URLWithString:PearlString(candidate, @"master_password")]; + + if ([application canOpenURL:url]) { + [application openURL:url]; + break; + } + } + return; + } + if (buttonIndex == [sheet firstOtherButtonIndex] + 3) { + // Mailing List + [PearlEMail sendEMailTo:@"masterpassword-join@lists.lyndir.com" subject:@"Subscribe" + body:@"Press 'Send' now to subscribe to the Master Password mailing list.\n\n" + @"You'll be kept up-to-date on the evolution of and discussions revolving Master Password."]; + return; + } + if (buttonIndex == [sheet firstOtherButtonIndex] + 4) { + // GitHub + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://github.com/Lyndir/MasterPassword"]]; + return; + } + } cancelTitle:[PearlStrings get].commonButtonCancel + destructiveTitle:nil otherTitles:@"Google+", @"Facebook", @"Twitter", @"Mailing List", @"GitHub", nil]; +} + - (void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error { switch (state) { diff --git a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard index 1ccf1f5f..c966b7cd 100644 --- a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard +++ b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard @@ -1465,6 +1465,36 @@ You could use the word wall for inspiration in finding a memorable master passw + + @@ -1974,8 +2004,10 @@ You could use the word wall for inspiration in finding a memorable master passw + +