mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-21 05:45:13 +00:00
359 lines
16 KiB
Mathematica
359 lines
16 KiB
Mathematica
![]() |
//
|
||
|
// OSKSessionController.m
|
||
|
// Overshare
|
||
|
//
|
||
|
// Created by Jared Sinclair on 10/11/13.
|
||
|
// Copyright (c) 2013 Overshare Kit. All rights reserved.
|
||
|
//
|
||
|
|
||
|
@import Accounts;
|
||
|
|
||
|
#import "OSKSessionController.h"
|
||
|
|
||
|
#import "OSKActivitiesManager.h"
|
||
|
#import "OSKActivity.h"
|
||
|
#import "OSKActivity_SystemAccounts.h"
|
||
|
#import "OSKActivity_GenericAuthentication.h"
|
||
|
#import "OSKActivity_ManagedAccounts.h"
|
||
|
#import "OSKActivitySheetViewController.h"
|
||
|
#import "OSKAppDotNetActivity.h"
|
||
|
#import "OSKAuthenticationViewController.h"
|
||
|
#import "OSKLogger.h"
|
||
|
#import "OSKPublishingViewController.h"
|
||
|
#import "OSKPurchasingViewController.h"
|
||
|
#import "OSKPresentationManager.h"
|
||
|
#import "OSKManagedAccount.h"
|
||
|
#import "OSKManagedAccountStore.h"
|
||
|
#import "OSKSystemAccountStore.h"
|
||
|
#import "OSKAlertView.h"
|
||
|
#import "OSKSession.h"
|
||
|
|
||
|
@interface OSKSessionController ()
|
||
|
<
|
||
|
OSKPurchasingViewControllerDelegate,
|
||
|
OSKAuthenticationViewControllerDelegate,
|
||
|
OSKPublishingViewControllerDelegate
|
||
|
>
|
||
|
|
||
|
@property (strong, nonatomic, readwrite) OSKSession *session;
|
||
|
@property ( weak, nonatomic, readwrite) id <OSKSessionControllerDelegate> delegate;
|
||
|
@property (strong, nonatomic, readwrite) OSKActivity *activity;
|
||
|
|
||
|
@end
|
||
|
|
||
|
@implementation OSKSessionController
|
||
|
|
||
|
- (instancetype)initWithActivity:(OSKActivity *)activity
|
||
|
session:(OSKSession *)session
|
||
|
delegate:(id<OSKSessionControllerDelegate>)delegate {
|
||
|
|
||
|
self = [super init];
|
||
|
if (self) {
|
||
|
_session = session;
|
||
|
_delegate = delegate;
|
||
|
_activity = activity;
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
#pragma mark - Tapped Activity Flow
|
||
|
|
||
|
- (void)start {
|
||
|
[self handlePurchasingStepForActivity:self.activity];
|
||
|
}
|
||
|
|
||
|
- (void)handlePurchasingStepForActivity:(OSKActivity *)activity {
|
||
|
if ([activity requiresPurchase]) {
|
||
|
if ([activity isAlreadyPurchased]) {
|
||
|
[self handleAuthenticationStepForActivity:activity];
|
||
|
} else {
|
||
|
[self showPurchasingViewControllerForActivity:activity];
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
[self handleAuthenticationStepForActivity:activity];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)handleAuthenticationStepForActivity:(OSKActivity *)activity {
|
||
|
OSKAuthenticationMethod authenticationMethod = [activity.class authenticationMethod];
|
||
|
if (authenticationMethod == OSKAuthenticationMethod_ManagedAccounts) {
|
||
|
[self handleManagedAccountAuthenticationStepForActivity:activity];
|
||
|
}
|
||
|
else if (authenticationMethod == OSKAuthenticationMethod_SystemAccounts) {
|
||
|
[self handleSystemAccountAuthenticationStepForActivity:activity];
|
||
|
}
|
||
|
else if (authenticationMethod == OSKAuthenticationMethod_Generic) {
|
||
|
[self handleGenericAuthenticationStepForActivity:activity];
|
||
|
}
|
||
|
else {
|
||
|
[self handlePublishingStepForActivity:activity];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)handleSystemAccountAuthenticationStepForActivity:(OSKActivity *)activity {
|
||
|
NSAssert([activity respondsToSelector:@selector(activeSystemAccount)], @"OSKActivity subclasses using the system account authentication method must conform to the OSKActivity_SystemAccounts protocol.");
|
||
|
OSKActivity <OSKActivity_SystemAccounts> *theActivity = (OSKActivity <OSKActivity_SystemAccounts> *)activity;
|
||
|
|
||
|
if ([[[theActivity class] activityType] isEqualToString:OSKActivityType_iOS_Facebook]) {
|
||
|
// Facebook accounts must request for read permissions before asking for write permissions
|
||
|
// (which is a maddening API decision). Thus, we must use a separate flow for Facebook authentication.
|
||
|
[self handleFacebookAccountAuthenticationStepForActivity:theActivity];
|
||
|
}
|
||
|
else {
|
||
|
OSKSystemAccountStore *accountStore = [OSKSystemAccountStore sharedInstance];
|
||
|
NSArray *existingAccounts = [accountStore accountsForAccountTypeIdentifier:[theActivity.class systemAccountTypeIdentifier]];
|
||
|
|
||
|
if (existingAccounts.count > 0) {
|
||
|
ACAccount *account = [existingAccounts firstObject];
|
||
|
[theActivity setActiveSystemAccount:account];
|
||
|
[self handlePublishingStepForActivity:activity];
|
||
|
}
|
||
|
else {
|
||
|
__weak OSKSessionController *weakSelf = self;
|
||
|
NSString *systemAccountTypeIdentifier = [theActivity.class systemAccountTypeIdentifier];
|
||
|
[accountStore requestAccessToAccountsWithAccountTypeIdentifier:systemAccountTypeIdentifier options:nil completion:^(BOOL successful, NSError *error) {
|
||
|
if (successful) {
|
||
|
NSArray *systemAccounts = [accountStore accountsForAccountTypeIdentifier:systemAccountTypeIdentifier];
|
||
|
if (systemAccounts.count > 0) {
|
||
|
ACAccount *account = [systemAccounts firstObject];
|
||
|
[theActivity setActiveSystemAccount:account];
|
||
|
[weakSelf handlePublishingStepForActivity:activity];
|
||
|
} else {
|
||
|
[weakSelf showAlertForNoSystemAccounts];
|
||
|
OSKLog(@"User has no existing system accounts with account type identifier: %@", systemAccountTypeIdentifier);
|
||
|
[weakSelf cancel];
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
[weakSelf showAlertForSystemAccountAccessNotGranted];
|
||
|
OSKLog(@"User denied access to system accounts with account type identifier: %@", systemAccountTypeIdentifier);
|
||
|
[weakSelf cancel];
|
||
|
}
|
||
|
}];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)handleFacebookAccountAuthenticationStepForActivity:(OSKActivity <OSKActivity_SystemAccounts>*)activity {
|
||
|
NSAssert([[[activity class] activityType] isEqualToString:OSKActivityType_iOS_Facebook], @"Attempting to authenticate a non-Facebook activity via the Facebook flow.");
|
||
|
OSKSystemAccountStore *accountStore = [OSKSystemAccountStore sharedInstance];
|
||
|
|
||
|
NSDictionary *readOptions = [activity.class readAccessRequestOptions];
|
||
|
NSDictionary *writeOptions = [activity.class writeAccessRequestOptions];
|
||
|
|
||
|
__weak OSKSessionController *weakSelf = self;
|
||
|
|
||
|
NSString *systemAccountTypeIdentifier = [activity.class systemAccountTypeIdentifier];
|
||
|
[accountStore requestAccessToAccountsWithAccountTypeIdentifier:systemAccountTypeIdentifier options:readOptions completion:^(BOOL successful, NSError *error) {
|
||
|
if (successful == NO) {
|
||
|
[weakSelf showAlertForSystemAccountAccessNotGranted];
|
||
|
OSKLog(@"Access request failed for system accounts with account type identifier: %@", systemAccountTypeIdentifier);
|
||
|
[weakSelf cancel];
|
||
|
}
|
||
|
else {
|
||
|
[accountStore requestAccessToAccountsWithAccountTypeIdentifier:systemAccountTypeIdentifier options:writeOptions completion:^(BOOL successful, NSError *error) {
|
||
|
if (successful == NO) {
|
||
|
[weakSelf showAlertForSystemAccountAccessNotGranted];
|
||
|
OSKLog(@"Access request failed for system accounts with account type identifier: %@", systemAccountTypeIdentifier);
|
||
|
[weakSelf cancel];
|
||
|
}
|
||
|
else {
|
||
|
NSArray *systemAccounts = [accountStore accountsForAccountTypeIdentifier:systemAccountTypeIdentifier];
|
||
|
if (systemAccounts.count > 0) {
|
||
|
ACAccount *account = [systemAccounts firstObject];
|
||
|
[activity setActiveSystemAccount:account];
|
||
|
[weakSelf handlePublishingStepForActivity:activity];
|
||
|
}
|
||
|
else {
|
||
|
[weakSelf showAlertForNoSystemAccounts];
|
||
|
OSKLog(@"User has no existing system accounts with account type identifier: %@", systemAccountTypeIdentifier);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}];
|
||
|
}
|
||
|
}];
|
||
|
}
|
||
|
|
||
|
- (void)showAlertForNoSystemAccounts {
|
||
|
OSKPresentationManager *presentationManger = [OSKPresentationManager sharedInstance];
|
||
|
NSString *title = [presentationManger localizedText_NoAccountsFound];
|
||
|
NSString *message = [presentationManger localizedText_YouCanSignIntoYourAccountsViaTheSettingsApp];
|
||
|
OSKAlertViewButtonItem *okayButton = [OSKAlertView okayItem];
|
||
|
OSKAlertView *alert = [[OSKAlertView alloc] initWithTitle:title message:message cancelButtonItem:okayButton otherButtonItems:nil];
|
||
|
[alert show];
|
||
|
}
|
||
|
|
||
|
- (void)showAlertForSystemAccountAccessNotGranted {
|
||
|
OSKPresentationManager *presentationManger = [OSKPresentationManager sharedInstance];
|
||
|
NSString *title = [presentationManger localizedText_AccessNotGrantedForSystemAccounts_Title];
|
||
|
NSString *message = [presentationManger localizedText_AccessNotGrantedForSystemAccounts_Message];
|
||
|
OSKAlertViewButtonItem *okayButton = [OSKAlertView okayItem];
|
||
|
OSKAlertView *alert = [[OSKAlertView alloc] initWithTitle:title message:message cancelButtonItem:okayButton otherButtonItems:nil];
|
||
|
[alert show];
|
||
|
}
|
||
|
|
||
|
- (void)finishUpAuthenticationWithFirstNewManagedAccount:(OSKManagedAccount *)account activity:(OSKActivity <OSKActivity_ManagedAccounts> *)activity {
|
||
|
OSKManagedAccountStore *accountStore = [OSKManagedAccountStore sharedInstance];
|
||
|
[accountStore addAccount:account forActivityType:[activity.class activityType]];
|
||
|
[activity setActiveManagedAccount:account];
|
||
|
[self handlePublishingStepForActivity:activity];
|
||
|
}
|
||
|
|
||
|
- (void)handleManagedAccountAuthenticationStepForActivity:(OSKActivity *)activity {
|
||
|
NSAssert([activity respondsToSelector:@selector(activeManagedAccount)], @"OSKActivity subclasses using the managed account authentication method must conform to the OSKActivity_ManagedAccounts protocol.");
|
||
|
OSKActivity <OSKActivity_ManagedAccounts> *theActivity = (OSKActivity <OSKActivity_ManagedAccounts> *)activity;
|
||
|
OSKManagedAccountStore *accountStore = [OSKManagedAccountStore sharedInstance];
|
||
|
NSArray *existingAccounts = [accountStore accountsForActivityType:[theActivity.class activityType]];
|
||
|
if (existingAccounts.count > 0) {
|
||
|
OSKManagedAccount *activeAccount = [accountStore activeAccountForActivityType:[activity.class activityType]];
|
||
|
[theActivity setActiveManagedAccount:activeAccount];
|
||
|
[self handlePublishingStepForActivity:theActivity];
|
||
|
}
|
||
|
else if ([theActivity.class authenticationViewControllerType] != OSKManagedAccountAuthenticationViewControllerType_None) {
|
||
|
[self showAuthenticationViewControllerForActivity:theActivity];
|
||
|
}
|
||
|
else {
|
||
|
__weak OSKSessionController *weakSelf = self;
|
||
|
[theActivity authenticateNewAccountWithoutViewController:^(OSKManagedAccount *account, NSError *error) {
|
||
|
if (account) {
|
||
|
[weakSelf finishUpAuthenticationWithFirstNewManagedAccount:account activity:theActivity];
|
||
|
} else {
|
||
|
OSKLog(@"Failed to add account for activity: %@ error: %@", activity, error);
|
||
|
[weakSelf cancel];
|
||
|
}
|
||
|
}];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)handleGenericAuthenticationStepForActivity:(OSKActivity *)activity {
|
||
|
NSAssert([activity respondsToSelector:@selector(authenticate:)], @"OSKActivity subclasses using the generic authentication method must conform to the OSKActivity_GenericAuthentication protocol.");
|
||
|
OSKActivity <OSKActivity_GenericAuthentication> *theActivity = (OSKActivity <OSKActivity_GenericAuthentication> *)activity;
|
||
|
if ([theActivity isAuthenticated]) {
|
||
|
[self handlePublishingStepForActivity:theActivity];
|
||
|
} else {
|
||
|
__weak OSKSessionController *weakSelf = self;
|
||
|
[theActivity authenticate:^(BOOL successful, NSError *error) {
|
||
|
if (successful) {
|
||
|
[weakSelf handlePublishingStepForActivity:theActivity];
|
||
|
} else {
|
||
|
OSKLog(@"Activity failed to authenticate: %@ error: %@", theActivity, error);
|
||
|
[weakSelf cancel];
|
||
|
}
|
||
|
}];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)handlePublishingStepForActivity:(OSKActivity *)activity {
|
||
|
if ([activity.class publishingViewControllerType] == OSKPublishingViewControllerType_None) {
|
||
|
[self dismissViewControllers];
|
||
|
[self handlePerformStepForActivity:activity];
|
||
|
} else {
|
||
|
[self showPublishingViewControllerForActivity:activity];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)handlePerformStepForActivity:(OSKActivity *)activity {
|
||
|
[self.delegate sessionControllerDidBeginPerformingActivity:self hasDismissedAllViewControllers:YES]; // Always YES for now...
|
||
|
__weak OSKSessionController *weakSelf = self;
|
||
|
[activity performActivity:^(OSKActivity *theActivity, BOOL successful, NSError *error) {
|
||
|
[weakSelf.delegate sessionControllerDidFinish:weakSelf successful:successful error:error];
|
||
|
}];
|
||
|
}
|
||
|
|
||
|
#pragma mark - Required for Subclasses
|
||
|
|
||
|
- (void)presentViewControllerAppropriately:(UIViewController *)viewController setAsNewRoot:(BOOL)isNewRoot {
|
||
|
NSAssert(NO, @"Subclasses must override presentViewControllerAppropriately:setAsNewRoot: without calling super");
|
||
|
}
|
||
|
|
||
|
- (void)presentSystemViewControllerAppropriately:(UIViewController *)systemViewController {
|
||
|
NSAssert(NO, @"Subclasses must override presentViewControllerAppropriately:setAsNewRoot: without calling super");
|
||
|
}
|
||
|
|
||
|
- (void)dismissViewControllers {
|
||
|
NSAssert(NO, @"Subclasses must override dismissAllViewControllers without calling super");
|
||
|
}
|
||
|
|
||
|
#pragma mark - Setting Up Purchasing View Controllers
|
||
|
|
||
|
- (void)showPurchasingViewControllerForActivity:(OSKActivity *)activity {
|
||
|
UIViewController <OSKPurchasingViewController> *viewController = nil;
|
||
|
viewController = [[OSKPresentationManager sharedInstance] purchasingViewControllerForActivity:activity];
|
||
|
[viewController preparePurchasingViewForActivity:activity delegate:self];
|
||
|
[self presentViewControllerAppropriately:viewController setAsNewRoot:YES];
|
||
|
}
|
||
|
|
||
|
#pragma mark - Setting Up Authentication View Controllers
|
||
|
|
||
|
- (void)showAuthenticationViewControllerForActivity:(OSKActivity *)activity {
|
||
|
UIViewController <OSKAuthenticationViewController> *viewController = nil;
|
||
|
viewController = [[OSKPresentationManager sharedInstance] authenticationViewControllerForActivity:activity];
|
||
|
[viewController prepareAuthenticationViewForActivity:(OSKActivity <OSKActivity_ManagedAccounts> *)activity delegate:self];
|
||
|
[self presentViewControllerAppropriately:viewController setAsNewRoot:YES];
|
||
|
}
|
||
|
|
||
|
#pragma mark - Setting Up Publishing View Controllers
|
||
|
|
||
|
- (void)showPublishingViewControllerForActivity:(OSKActivity *)activity {
|
||
|
UIViewController <OSKPublishingViewController> *viewController = nil;
|
||
|
viewController = [[OSKPresentationManager sharedInstance] publishingViewControllerForActivity:activity];
|
||
|
[viewController preparePublishingViewForActivity:activity delegate:self];
|
||
|
if ([activity.class publishingViewControllerType] == OSKPublishingViewControllerType_System) {
|
||
|
[self presentSystemViewControllerAppropriately:viewController];
|
||
|
} else {
|
||
|
[self presentViewControllerAppropriately:viewController setAsNewRoot:YES];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#pragma mark - Purchasing View Controller Delegate
|
||
|
|
||
|
- (void)purchasingViewController:(UIViewController <OSKPurchasingViewController> *)viewController didPurchaseActivityTypes:(NSArray *)activityTypes withActivity:(OSKActivity *)activity {
|
||
|
OSKActivitiesManager *manager = [OSKActivitiesManager sharedInstance];
|
||
|
[manager markActivityTypes:activityTypes asAlreadyPurchased:YES];
|
||
|
[self handleAuthenticationStepForActivity:activity];
|
||
|
}
|
||
|
|
||
|
- (void)purchasingViewControllerDidCancel:(UIViewController <OSKPurchasingViewController> *)viewController withActivity:(OSKActivity *)activity {
|
||
|
[self cancel];
|
||
|
}
|
||
|
|
||
|
#pragma mark - Authentication View Controller Delegate
|
||
|
|
||
|
- (void)authenticationViewController:(UIViewController <OSKAuthenticationViewController> *)viewController didAuthenticateNewAccount:(OSKManagedAccount *)account withActivity:(OSKActivity *)activity {
|
||
|
[self finishUpAuthenticationWithFirstNewManagedAccount:account activity:(OSKActivity <OSKActivity_ManagedAccounts> *)activity];
|
||
|
}
|
||
|
|
||
|
- (void)authenticationViewControllerDidCancel:(UIViewController <OSKAuthenticationViewController> *)viewController withActivity:(OSKActivity *)activity {
|
||
|
[self cancel];
|
||
|
}
|
||
|
|
||
|
#pragma mark - Publishing View Controller Delegate
|
||
|
|
||
|
- (void)publishingViewController:(UIViewController <OSKPublishingViewController> *)viewController didTapPublishActivity:(OSKActivity *)activity {
|
||
|
if ([activity isReadyToPerform]) {
|
||
|
[self dismissViewControllers];
|
||
|
[self handlePerformStepForActivity:activity];
|
||
|
} else {
|
||
|
OSKLog(@"Publishing failed, not yet ready to perform: %@", activity);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)publishingViewControllerDidCancel:(UIViewController <OSKPublishingViewController> *)viewController
|
||
|
withActivity:(OSKActivity *)activity {
|
||
|
[self cancel];
|
||
|
}
|
||
|
|
||
|
#pragma mark - Convenience
|
||
|
|
||
|
- (void)cancel {
|
||
|
[self dismissViewControllers];
|
||
|
[self.delegate sessionControllerDidCancel:self];
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
|
||
|
|