2
0

Sharing on Facebook, Twitter and Google+

[FIXED]     Font of navbar.
[FIXED]     A few compile fixes.
[IMPROVED]  Made properties nonatomic.
[ADDED]     Support for facebook, twitter and google+ sharing.
This commit is contained in:
Maarten Billemont
2012-08-25 12:38:29 +02:00
parent b9ccee398e
commit 5e7b6ed60e
131 changed files with 24758 additions and 26 deletions

View File

@@ -11,7 +11,7 @@
@interface MPAppDelegate_Shared ()
@property (strong) NSManagedObjectID *activeUserID;
@property (strong, nonatomic) NSManagedObjectID *activeUserID;
@end

View File

@@ -177,7 +177,7 @@
Throw(@"Local store was reset, application must be restarted to use it.");
} else
// Try again.
[self storeManager].persistentStoreCoordinator;
[[self storeManager] persistentStoreCoordinator];
}
case UbiquityStoreManagerErrorCauseOpenCloudStore: {
wrn(@"iCloud store could not be opened: %@", error);
@@ -194,7 +194,7 @@
break;
} else
// Try again.
[self storeManager].persistentStoreCoordinator;
[[self storeManager] persistentStoreCoordinator];
}
}
}

View File

@@ -6,6 +6,8 @@
// Copyright (c) 2011 Lyndir. All rights reserved.
//
#import <FacebookSDK/FacebookSDK.h>
#import "MPAppDelegate.h"
#import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h"
@@ -148,7 +150,7 @@
@{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:@"Helvetica-Neue" size:0.0f]}
UITextAttributeFont: [UIFont fontWithName:@"HelveticaNeue" size:0.0f]}
forState:UIControlStateNormal];
UIImage *toolBarImage = [[UIImage imageNamed:@"ui_toolbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(25, 5, 5, 5)];
@@ -215,7 +217,25 @@
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
// No URL?
if (!url)
return NO;
// Check if this is a Facebook login URL.
if ([FBSession.activeSession handleOpenURL:url])
return YES;
// Arbitrary URL to mpsites data.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error;
NSURLResponse *response;
NSData *importedSitesData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url]
returningResponse:&response error:&error];
if (error)
err(@"While reading imported sites from %@: %@", url, error);
if (!importedSitesData)
return;
PearlAlert *activityAlert = [PearlAlert showAlertWithTitle:@"Importing" message:@"\n\n"
viewStyle:UIAlertViewStyleDefault initAlert:
^(UIAlertView *alert, UITextField *firstField) {
@@ -226,15 +246,6 @@
}
tappedButtonBlock:nil cancelTitle:nil otherTitles:nil];
NSError *error;
NSURLResponse *response;
NSData *importedSitesData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url]
returningResponse:&response error:&error];
if (error)
err(@"While reading imported sites from %@: %@", url, error);
if (!importedSitesData)
return;
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
__block NSString *masterPassword = nil;
@@ -325,6 +336,10 @@
[TestFlight passCheckpoint:MPCheckpointActivated];
if (FBSession.activeSession.state == FBSessionStateCreatedOpening)
// An old Facebook Login session that wasn't finished. Clean it up.
[FBSession.activeSession close];
[super applicationDidBecomeActive:application];
}
@@ -353,6 +368,8 @@
[[LocalyticsSession sharedLocalyticsSession] close];
[[LocalyticsSession sharedLocalyticsSession] upload];
[FBSession.activeSession close];
[super applicationWillTerminate:application];
}

View File

@@ -13,7 +13,7 @@
@interface MPMainViewController : UIViewController<MPTypeDelegate, UITextFieldDelegate, MPSearchResultsDelegate, UIWebViewDelegate, MFMailComposeViewControllerDelegate, UIGestureRecognizerDelegate>
@property (nonatomic, assign) BOOL siteInfoHidden;
@property (assign, nonatomic) BOOL siteInfoHidden;
@property (strong, nonatomic) MPElementEntity *activeElement;
@property (strong, nonatomic) IBOutlet MPSearchDelegate *searchDelegate;
@property (weak, nonatomic) IBOutlet UITextField *contentField;
@@ -48,8 +48,8 @@
@property (weak, nonatomic) IBOutlet UIButton *outdatedAlertCloseButton;
@property (copy) void (^contentTipCleanup)(BOOL finished);
@property (copy) void (^toolTipCleanup)(BOOL finished);
@property (copy, nonatomic) void (^contentTipCleanup)(BOOL finished);
@property (copy, nonatomic) void (^toolTipCleanup)(BOOL finished);
- (IBAction)copyContent;
- (IBAction)incrementPasswordCounter;

View File

@@ -122,6 +122,9 @@
if ([[MPiOSConfig get].showQuickStart boolValue])
[[MPAppDelegate get] showGuide];
if (![MPAppDelegate get].activeUser)
[self.navigationController presentViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"MPUnlockViewController"]
animated:animated completion:nil];
if (self.activeElement.user != [MPAppDelegate get].activeUser)
self.activeElement = nil;
@@ -141,6 +144,8 @@
- (void)viewDidAppear:(BOOL)animated {
// Needed for when we appear after a modal VC dismisses:
// We can't present until the other modal VC has been fully dismissed and presenting in viewDidAppear will fail.
if (![MPAppDelegate get].activeUser)
[self.navigationController presentViewController:[self.storyboard instantiateViewControllerWithIdentifier:@"MPUnlockViewController"]
animated:animated completion:nil];

View File

@@ -29,5 +29,8 @@
@property (nonatomic, strong) UIColor *avatarShadowColor;
- (IBAction)targetedUserAction:(UILongPressGestureRecognizer *)sender;
- (IBAction)facebook:(UIButton *)sender;
- (IBAction)twitter:(UIButton *)sender;
- (IBAction)google:(UIButton *)sender;
@end

View File

@@ -7,6 +7,10 @@
//
#import <QuartzCore/QuartzCore.h>
#import <Twitter/Twitter.h>
#import "Facebook.h"
#import "GooglePlusShare.h"
#import "MPUnlockViewController.h"
#import "MPAppDelegate.h"
@@ -18,7 +22,8 @@
@property (strong, nonatomic) MPUserEntity *selectedUser;
@property (strong, nonatomic) NSMutableDictionary *avatarToUser;
@property (nonatomic) BOOL wordWallAnimating;
@property (nonatomic, strong) NSArray *wordList;
@property (nonatomic, strong) NSArray *wordList;
@property (nonatomic, strong) NSOperationQueue *fbOperationQueue;
@end
@@ -43,6 +48,7 @@
@synthesize avatarShadowColor = _avatarShadowColor;
@synthesize wordWallAnimating = _wordWallAnimating;
@synthesize wordList = _wordList;
@synthesize fbOperationQueue = _fbOperationQueue;
- (void)initializeAvatarAlert:(UIAlertView *)alert forUser:(MPUserEntity *)user {
@@ -122,7 +128,9 @@
- (void)viewDidLoad {
self.avatarToUser = [NSMutableDictionary dictionaryWithCapacity:3];
self.avatarToUser = [NSMutableDictionary dictionaryWithCapacity:3];
self.fbOperationQueue = [NSOperationQueue new];
[self.fbOperationQueue setSuspended:YES];
self.avatarsView.decelerationRate = UIScrollViewDecelerationRateFast;
self.avatarsView.clipsToBounds = NO;
@@ -283,7 +291,7 @@
if ([self.selectedUser.objectID isEqual:user.objectID]) {
self.selectedUser = user;
avatar.selected = YES;
avatar.selected = YES;
}
return avatar;
@@ -407,9 +415,9 @@
if (self.selectedUser && !self.passwordView.alpha) {
// User was just selected.
self.passwordView.alpha = 1;
self.avatarsView.center = CGPointMake(160, 170);
self.avatarsView.center = CGPointMake(160, 180);
self.avatarsView.scrollEnabled = NO;
self.nameLabel.center = CGPointMake(160, 84);
self.nameLabel.center = CGPointMake(160, 94);
self.nameLabel.backgroundColor = [UIColor blackColor];
self.oldNameLabel.center = self.nameLabel.center;
self.avatarShadowColor = [UIColor whiteColor];
@@ -764,4 +772,81 @@
} cancelTitle:[PearlStrings get].commonButtonCancel
destructiveTitle:@"Delete User" otherTitles:@"Reset Password", nil];
}
- (IBAction)facebook:(UIButton *)sender {
[self.fbOperationQueue addOperationWithBlock:^{
Facebook *facebook = [[Facebook alloc] initWithAppId:FBSession.activeSession.appID andDelegate:nil];
facebook.accessToken = FBSession.activeSession.accessToken;
facebook.expirationDate = FBSession.activeSession.expirationDate;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[[self.view findFirstResponderInHierarchy] resignFirstResponder];
[facebook dialog:@"feed" andParams:[@{
@"link": @"http://masterpasswordapp.com",
@"picture": @"http://masterpasswordapp.com/img/iTunesArtwork-Rounded.png",
@"name": @"Master Password",
@"description": @"Actually secure passwords that cannot get lost.",
@"ref": @"iOS_Unlock"
} mutableCopy] andDelegate:nil];
}];
}];
if ([self.fbOperationQueue isSuspended])
[self openSessionWithAllowLoginUI:YES];
}
- (IBAction)twitter:(UIButton *)sender {
if (![TWTweetComposeViewController canSendTweet]) {
[PearlAlert showAlertWithTitle:@"Twitter Not Enabled" message:@"To send tweets, configure Twitter from Settings."
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:nil cancelTitle:nil otherTitles:@"OK", nil];
return;
}
TWTweetComposeViewController *vc = [TWTweetComposeViewController new];
[vc addImage:[UIImage imageNamed:@"iTunesArtwork-Rounded-73"]];
[vc setInitialText:@"I've secured my accounts with Master Password: masterpasswordapp.com"];
[self presentViewController:vc animated:YES completion:nil];
}
- (IBAction)google:(UIButton *)sender {
GooglePlusShare *share = [[GooglePlusShare alloc] initWithClientID:[[PearlInfoPlist get] objectForKeyPath:@"GooglePlusClientID"]];
[[[[share shareDialog]
setURLToShare:[NSURL URLWithString:@"http://masterpasswordapp.com"]]
setPrefillText:@"I've secured my accounts with Master Password: Actually secure passwords that cannot get lost."]
open];
}
- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error {
switch (state) {
case FBSessionStateOpen:
if (!error) {
[self.fbOperationQueue setSuspended:NO];
return;
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
[self.fbOperationQueue setSuspended:YES];
if (error)
[PearlAlert showError:error.localizedDescription];
}
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
return [FBSession openActiveSessionWithPermissions:nil allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
}
@end

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="2.0" toolsVersion="2549" systemVersion="12A269" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="KZF-fe-y9n">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="2.0" toolsVersion="2549" systemVersion="12B19" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="KZF-fe-y9n">
<dependencies>
<deployment defaultVersion="1296" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="1498"/>
</dependencies>
<scenes>
@@ -1143,7 +1144,7 @@ Pink fluffy door frame.</string>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_spinner.png" id="27q-lX-0vy">
<rect key="frame" x="105" y="30" width="110" height="110"/>
<rect key="frame" x="105" y="40" width="110" height="110"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<view contentMode="scaleToFill" id="JTj-nh-BWs" userLabel="Word Wall">
@@ -1306,7 +1307,7 @@ Pink fluffy door frame.</string>
<color key="shadowColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</label>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" indicatorStyle="white" delaysContentTouches="NO" id="Blg-F1-9NA">
<rect key="frame" x="0.0" y="0.0" width="320" height="340"/>
<rect key="frame" x="0.0" y="10" width="320" height="340"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" showsTouchWhenHighlighted="YES" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="Ten-ig-gog">
@@ -1338,7 +1339,7 @@ Pink fluffy door frame.</string>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="10" id="0NM-NI-7UR">
<rect key="frame" x="90" y="77" width="140" height="15"/>
<rect key="frame" x="90" y="86.5" width="140" height="15"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Futura-CondensedExtraBold" family="Futura" pointSize="13"/>
@@ -1419,6 +1420,51 @@ You could use the word wall for inspiration in finding a memorable master passw
<rect key="frame" x="142" y="415" width="37" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</activityIndicatorView>
<button opaque="NO" alpha="0.20000000000000015" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="5Qz-dA-cgl" userLabel="facebook">
<rect key="frame" x="84" y="0.0" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" backgroundImage="social-facebook.png">
<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="facebook:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="Sup-Dp-WHn"/>
</connections>
</button>
<button opaque="NO" alpha="0.20000000000000015" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="eeS-3V-WSf" userLabel="twitter">
<rect key="frame" x="138" y="0.0" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" backgroundImage="social-twitter.png">
<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="twitter:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="491-Kf-UAK"/>
</connections>
</button>
<button opaque="NO" alpha="0.20000000000000015" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="tGv-v7-kcX" userLabel="google+">
<rect key="frame" x="192" y="0.0" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" backgroundImage="social-google+.png">
<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="google:" destination="Nbn-Rv-sP1" eventType="touchUpInside" id="5T6-yt-7jv"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
@@ -1823,6 +1869,9 @@ You could use the word wall for inspiration in finding a memorable master passw
<image name="icon_person.png" width="32" height="32"/>
<image name="icon_plus.png" width="32" height="32"/>
<image name="icon_up.png" width="32" height="32"/>
<image name="social-facebook.png" width="44" height="44"/>
<image name="social-google+.png" width="44" height="44"/>
<image name="social-twitter.png" width="44" height="44"/>
<image name="tip_alert_black.png" width="235" height="81"/>
<image name="tip_basic_black.png" width="210" height="60"/>
<image name="tip_basic_black_bottom_right.png" width="210" height="60"/>
@@ -1925,7 +1974,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="facebook:" candidateClass="UIButton"/>
<relationship kind="action" name="google:" candidateClass="UIButton"/>
<relationship kind="action" name="targetedUserAction:" candidateClass="UILongPressGestureRecognizer"/>
<relationship kind="action" name="twitter:" candidateClass="UIButton"/>
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
<relationship kind="outlet" name="createPasswordTipView" candidateClass="UIView"/>

View File

@@ -61,8 +61,35 @@
<string>[auto]</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>facebook</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fb257095917745237</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.lyndir.lhunath.MasterPassword</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.lyndir.lhunath.MasterPassword</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>[auto]</string>
<key>FacebookAppID</key>
<string>257095917745237</string>
<key>GooglePlusClientID</key>
<string>1098891429568.apps.googleusercontent.com</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSHumanReadableCopyright</key>