Navigation Menu

Skip to content
This repository has been archived by the owner on Mar 7, 2023. It is now read-only.

Commit

Permalink
Add ability to open up a guide based on URL Scheme
Browse files Browse the repository at this point in the history
This will allow the user to go straight to a guide depending on the URL scheme
it was given. This also accounts for private sites (requiring login from the
user, THEN sending them to the specified guide).
  • Loading branch information
Stefan Ayala committed Mar 27, 2013
1 parent 99f433b commit 0c658f9
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 46 deletions.
1 change: 1 addition & 0 deletions Classes/LoginViewController.h
Expand Up @@ -12,6 +12,7 @@
@interface LoginViewController : UITableViewController <UITextFieldDelegate, UIGestureRecognizerDelegate>

@property (nonatomic, assign) id<LoginViewControllerDelegate> delegate;
@property (nonatomic, retain) id viewToPresentOnSuccess;
@property (nonatomic, copy) NSString *message;
@property (nonatomic, retain) WBProgressHUD *loading;
@property (nonatomic) BOOL showRegister;
Expand Down
7 changes: 7 additions & 0 deletions Classes/LoginViewController.m
Expand Up @@ -14,6 +14,7 @@
#import "Config.h"
#import "OpenIDViewController.h"
#import "SSOViewController.h"
#import "GuideViewController.h"

@implementation LoginViewController

Expand All @@ -35,6 +36,7 @@ - (id)init {
self.loginButton = nil;
self.registerButton = nil;
self.cancelButton = nil;
self.viewToPresentOnSuccess = nil;
}
return self;
}
Expand Down Expand Up @@ -567,6 +569,11 @@ - (void)loginResults:(NSDictionary *)results {

// The delegate is responsible for removing the login view.
[delegate refresh];

// If we were given a view controller to present, lets use it
if (self.viewToPresentOnSuccess) {
[delegate presentModalViewController:self.viewToPresentOnSuccess animated:NO];
}
}

[self hideLoading];
Expand Down
121 changes: 76 additions & 45 deletions Classes/iFixitAppDelegate.m
Expand Up @@ -69,11 +69,11 @@ @implementation iFixitAppDelegate
- (void)setupAnalytics {
if ([Config currentConfig].dozuki)
return;

[[GANTracker sharedTracker] startTrackerWithAccountID:@"UA-30506-9"
dispatchPeriod:kGANDispatchPeriodSec
delegate:nil];

[[GANTracker sharedTracker] setCustomVariableAtIndex:1
name:@"model"
value:[UIDevice currentDevice].model
Expand All @@ -82,7 +82,7 @@ - (void)setupAnalytics {
name:@"systemVersion"
value:[UIDevice currentDevice].systemVersion
withError:NULL];

[[GANTracker sharedTracker] trackPageview:[NSString stringWithFormat:@"/launch/%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]] withError:NULL];
}

Expand All @@ -94,11 +94,11 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
/* Track. */
[TestFlight takeOff:@"6b356258f037dc15f6d69d0e5d27fdf7_MzAyOTUyMDEyLTAyLTEyIDE1OjQ2OjUwLjA0NTg5OQ"];
[self setupAnalytics];

/* iOS 5 appearance */
if ([UITabBar respondsToSelector:@selector(appearance)])
[[UITabBar appearance] setBackgroundImage:[UIImage imageNamed:@"customTabBarBackground.png"]];

/* Setup and launch. */
self.window.rootViewController = nil;
firstLoad = YES;
Expand All @@ -118,24 +118,24 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
else {
[self showDozukiSplash];
}

firstLoad = NO;
}

return YES;
}

- (void)showDozukiSplash {
[detailViewController.popoverController dismissPopoverAnimated:NO];

// Make sure we're not pointing at a site requiring setup.
[[Config currentConfig] setSite:ConfigIFixit];

// Reset the saved choice.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:nil forKey:@"site"];
[defaults synchronize];

// Dozuki splash
DozukiSplashViewController *dsvc = [[DozukiSplashViewController alloc] init];
dsvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
Expand All @@ -155,7 +155,7 @@ - (void)showSiteSplash {
for (UIView *subview in self.window.subviews)
[subview removeFromSuperview];
}

UIViewController *root = nil;
UINavigationController *nvc = nil;

Expand All @@ -164,13 +164,13 @@ - (void)showSiteSplash {
LoginViewController *vc = [[LoginViewController alloc] init];
vc.message = @"Private site. Authentication required.";
vc.delegate = self;
nvc = [[[UINavigationController alloc] initWithRootViewController:vc] autorelease];
nvc = [[[UINavigationController alloc] initWithRootViewController:vc] autorelease];
nvc.modalPresentationStyle = UIModalPresentationFormSheet;
nvc.navigationBar.tintColor = [Config currentConfig].toolbarColor;
[vc release];

UIImage *icon = [UIImage imageNamed:@"backtosites.png"];

// We only need this button if on Dozuki
if ([Config currentConfig].dozuki) {
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:icon style:UIBarButtonItemStyleBordered
Expand Down Expand Up @@ -198,7 +198,7 @@ - (void)showSiteSplash {
root = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad ?
[self iPadRoot] : [self iPhoneRoot];
}

self.window.rootViewController = root;
[window makeKeyAndVisible];
}
Expand All @@ -210,52 +210,52 @@ - (void)refresh {
}

- (void)presentModalViewController:(UIViewController *)viewController animated:(BOOL)animated {
[self.window.rootViewController presentModalViewController:viewController animated:animated];
[self.window.rootViewController presentModalViewController:viewController animated:animated];
}

- (UIViewController *)iPadRoot {
self.showsTabBar = [Config currentConfig].collectionsEnabled || [Config currentConfig].store;

// Create the split controller children.
CategoriesViewController *rvc = [[CategoriesViewController alloc] init];
self.categoriesViewController = rvc;
[rvc release];
DetailViewController *dvc = [[DetailViewController alloc] init];
self.detailViewController = dvc;
[dvc release];

// Create the split view controller.
UISplitViewController *svc = [[UISplitViewController alloc] init];
svc.delegate = detailViewController;
self.splitViewController = svc;
[svc release];

categoriesViewController.detailViewController = detailViewController;

ListViewController *lvc = [[ListViewController alloc] initWithRootViewController:categoriesViewController];
splitViewController.viewControllers = [NSArray arrayWithObjects:lvc, detailViewController, nil];
[lvc release];

categoriesViewController.delegate = self;

// Stop here, or put a fancy tab bar at the bottom.
if (!self.showsTabBar)
return splitViewController;

// Initialize the tab bar items.
NSString *guideTitle = @"Guides";
if ([Config currentConfig].site == ConfigMake)
guideTitle = @"Projects";
else if ([Config currentConfig].site == ConfigIFixit)
guideTitle = @"Repair Manuals";

if ([Config currentConfig].site == ConfigIFixit) {
splitViewController.tabBarItem = [[[UITabBarItem alloc] initWithTitle:guideTitle image:[UIImage imageNamed:@"tabBarItemWrench.png"] tag:0] autorelease];
}
else {
splitViewController.tabBarItem = [[[UITabBarItem alloc] initWithTitle:guideTitle image:[UIImage imageNamed:@"tabBarItemBook.png"] tag:0] autorelease];
}

// Optionally add the store button.
SVWebViewController *storeViewController = nil;
NSString *storeTitle = @"Store";
Expand All @@ -268,15 +268,15 @@ - (UIViewController *)iPadRoot {
}
storeViewController = [[SVWebViewController alloc] initWithAddress:[Config currentConfig].store];
storeViewController.tintColor = [Config currentConfig].toolbarColor;
storeViewController.showsDoneButton = NO;
storeViewController.showsDoneButton = NO;
storeViewController.tabBarItem = [[[UITabBarItem alloc] initWithTitle:storeTitle image:storeImage tag:0] autorelease];
}

// Create the tab bar.
UITabBarController *tbc = [[UITabBarController alloc] init];

if ([Config currentConfig].collectionsEnabled) {
FeaturedViewController *featuredViewController = [[FeaturedViewController alloc] init];
FeaturedViewController *featuredViewController = [[FeaturedViewController alloc] init];
featuredViewController.tabBarItem = [[[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:0] autorelease];
tbc.viewControllers = [NSArray arrayWithObjects:featuredViewController, splitViewController, storeViewController, nil];
[featuredViewController release];
Expand All @@ -286,15 +286,15 @@ - (UIViewController *)iPadRoot {
}

[storeViewController release];

return [tbc autorelease];
}

- (UIViewController *)iPhoneRoot {
CategoriesViewController *cvc = [[CategoriesViewController alloc] init];
self.categoriesViewController = cvc;
[cvc release];

ListViewController *lvc = [[ListViewController alloc] initWithRootViewController:categoriesViewController];

lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
Expand All @@ -310,7 +310,7 @@ - (void)loadSite:(NSDictionary *)site {
NSString *domain = [site valueForKey:@"domain"];
//NSString *colorHex = [site valueForKey:@"color"];
//UIColor *color = [UIColor colorFromHexString:colorHex];

// Load the right site
if ([domain isEqual:@"www.ifixit.com"]) {
[[Config currentConfig] setSite:ConfigIFixit];
Expand All @@ -326,11 +326,11 @@ - (void)loadSite:(NSDictionary *)site {
[Config currentConfig].host = domain;
[Config currentConfig].custom_domain = [site valueForKey:@"custom_domain"];
[Config currentConfig].baseURL = [NSString stringWithFormat:@"http://%@/Guide", domain];

//if (color)
// [Config currentConfig].toolbarColor = color;
}

// Enable/disable Answers and/or Collections
if ([Config currentConfig].site == ConfigIFixit) {
[Config currentConfig].answersEnabled = YES;
Expand All @@ -344,7 +344,7 @@ - (void)loadSite:(NSDictionary *)site {
[Config currentConfig].private = [[site valueForKey:@"private"] boolValue];
[Config currentConfig].sso = [[site valueForKey:@"authentication"] valueForKey:@"sso"];
[Config currentConfig].store = [site valueForKey:@"store"];

// Save this choice for future launches, first removing any null values.
NSMutableDictionary *simpleSite = [NSMutableDictionary dictionary];
for (NSString *key in [site allKeys]) {
Expand All @@ -354,16 +354,15 @@ - (void)loadSite:(NSDictionary *)site {
}
[[NSUserDefaults standardUserDefaults] setValue:simpleSite forKey:@"site"];
[[NSUserDefaults standardUserDefaults] synchronize];

[Config currentConfig].siteData = simpleSite;

// Show the main app!
[[iFixitAPI sharedInstance] loadSession];
[self showSiteSplash];
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {

NSString *urlString = [url absoluteString];

// Pull out the site name with a regex.
Expand All @@ -373,42 +372,74 @@ - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^dozuki://(.*?)$"
options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:urlString options:0 range:NSMakeRange(0, [urlString length])];

if (match) {
NSRange keyRange = [match rangeAtIndex:1];
NSString *domain = [urlString substringWithRange:keyRange];
NSDictionary *site = [NSDictionary dictionaryWithObject:domain forKey:@"domain"];

[[NSUserDefaults standardUserDefaults] setValue:site forKey:@"site"];
[[NSUserDefaults standardUserDefaults] synchronize];

[self loadSite:site];
return YES;
}
}
}
else {
} else if ([Config currentConfig].site == ConfigHaas2) {
// Flesh this out if we ever want to put this into production, for demo purposes this is OKAY
// I hate myself for coding it this way but again, demo purposes! I am crying as I type this.
int guideid = [[urlString stringByReplacingOccurrencesOfString:@"haas2:guideid=" withString:@""] intValue];

// kill an ant with a cannon. Essentially resetting the app to avoid weird edge cases. If
// we put this into production, make this smarter
[self application:application didFinishLaunchingWithOptions:nil];

GuideViewController *vc = [[GuideViewController alloc] initWithGuideid:guideid];

// Present view if user is already logged in
if ([iFixitAPI sharedInstance].user) {
[self.window.rootViewController presentModalViewController:vc animated:NO];
} else {
// Create login view controller
LoginViewController *lvc = [[LoginViewController alloc] init];
lvc.message = @"Private site. Authentication Required.";
lvc.delegate = self;
lvc.viewToPresentOnSuccess = vc;

// Create navigation view controller, init with newly created view controller
UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:lvc];
nvc.navigationBar.tintColor = [Config currentConfig].toolbarColor;

// Present navigation controller
[self.window.rootViewController presentModalViewController:nvc animated:NO];
[nvc release];
}
[vc release];

return YES;
// iFixit
} else {
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^ifixit://guide/(.*?)$"
options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:urlString options:0 range:NSMakeRange(0, [urlString length])];

if (match) {
NSRange keyRange = [match rangeAtIndex:1];
NSString *guideidString = [urlString substringWithRange:keyRange];
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *guideid = [f numberFromString:guideidString];
[f release];

GuideViewController *vc = [[GuideViewController alloc] initWithGuideid:[guideid intValue]];
[self.window.rootViewController presentModalViewController:vc animated:NO];
[vc release];

return YES;
}
}

return NO;
}

Expand Down
2 changes: 1 addition & 1 deletion iFixit-Info.plist
Expand Up @@ -53,7 +53,7 @@
<string>com.ifixit.ifixit</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ifixit</string>
<string>haas2</string>
</array>
</dict>
</array>
Expand Down

1 comment on commit 0c658f9

@BaseInfinity
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Urls need to be in the form of

"haas2:guideid=4"

Please sign in to comment.