2
0

Follow on social networks.

[UPDATED]   Migrated from MFMailComposeViewController to PearlEMail.
[ADDED]     Social network "follow" button.
This commit is contained in:
Maarten Billemont
2012-08-26 17:40:32 +02:00
parent 5e7b6ed60e
commit ca9cbc9fd1
9 changed files with 211 additions and 138 deletions

View File

@@ -10,12 +10,13 @@
#import <MessageUI/MessageUI.h>
#import "MPAppDelegate_Shared.h"
@interface MPAppDelegate : MPAppDelegate_Shared<MFMailComposeViewControllerDelegate>
@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;

View File

@@ -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 <masterpassword@lyndir.com>"
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 {

View File

@@ -11,7 +11,7 @@
#import "MPElementEntity.h"
#import "MPSearchDelegate.h"
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPSearchResultsDelegate, UIWebViewDelegate, MFMailComposeViewControllerDelegate, UIGestureRecognizerDelegate>
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPSearchResultsDelegate, UIWebViewDelegate, UIGestureRecognizerDelegate>
@property (assign, nonatomic) BOOL siteInfoHidden;
@property (strong, nonatomic) MPElementEntity *activeElement;

View File

@@ -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 <masterpassword@lyndir.com>"]];
[composer setSubject:PearlString(@"Feedback for Master Password [%@]",
[[PearlKeyChain deviceIdentifier] stringByDeletingMatchesOf:@"-.*"])];
[composer setMessageBody:
PearlString(
@"\n\n\n"
@"--\n"
@"%@\n"
@"Master Password %@, build %@",
[MPAppDelegate get].activeUser.name,
[PearlInfoPlist get].CFBundleShortVersionString,
[PearlInfoPlist get].CFBundleVersion)
isHTML:NO];
if (buttonIndex_ == [alert_ firstOtherButtonIndex]) {
PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug
: PearlLogLevelInfo;
[composer addAttachmentData:[[[PearlLogger get] formatMessagesWithLevel:logLevel] dataUsingEncoding:NSUTF8StringEncoding]
mimeType:@"text/plain"
fileName:PearlString(@"%@-%@.log",
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]],
[PearlKeyChain deviceIdentifier])];
}
[self presentModalViewController:composer animated:YES];
}
cancelTitle:nil otherTitles:@"Include Logs", @"No Logs", nil];
}
[[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;

View File

@@ -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

View File

@@ -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) {

View File

@@ -1465,6 +1465,36 @@ You could use the word wall for inspiration in finding a memorable master passw
<action selector="google:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="5T6-yt-7jv"/>
</connections>
</button>
<button opaque="NO" alpha="0.10000000000000001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="vM2-8p-qn7" userLabel="mail">
<rect key="frame" x="276" y="0.0" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
<state key="normal" title="✉">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="mail:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="f6b-uF-NNs"/>
</connections>
</button>
<button opaque="NO" alpha="0.10000000000000001" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="2dq-bb-mPl" userLabel="add">
<rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="26"/>
<state key="normal" title="">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="add:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="Fee-sf-mIv"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
@@ -1974,8 +2004,10 @@ You could use the word wall for inspiration in finding a memorable master passw
<class className="MPUnlockViewController" superclassName="UIViewController">
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPUnlockViewController.h"/>
<relationships>
<relationship kind="action" name="add:" candidateClass="UIButton"/>
<relationship kind="action" name="facebook:" candidateClass="UIButton"/>
<relationship kind="action" name="google:" candidateClass="UIButton"/>
<relationship kind="action" name="mail:" candidateClass="UIButton"/>
<relationship kind="action" name="targetedUserAction:" candidateClass="UILongPressGestureRecognizer"/>
<relationship kind="action" name="twitter:" candidateClass="UIButton"/>
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>