From d52c86da9751f221a24c21ec903656e279ba885a Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sun, 2 Feb 2014 00:53:45 +0400 Subject: Login info in reveal panel and login flow improvements (not complete) --- Juick.xcodeproj/project.pbxproj | 12 +++++++ Juick/AppDelegate.h | 2 ++ Juick/AppDelegate.m | 14 ++++++-- Juick/LoginViewController.m | 20 ++++++++---- Juick/RevealPanelViewController.h | 8 +++-- Juick/RevealPanelViewController.m | 60 +++++++++++++++++++++++++++++++---- Juick/TitleView.h | 19 +++++++++++ Juick/TitleView.m | 37 +++++++++++++++++++++ Juick/User.h | 24 ++++++++++++++ Juick/User.m | 67 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 246 insertions(+), 17 deletions(-) create mode 100644 Juick/TitleView.h create mode 100644 Juick/TitleView.m create mode 100644 Juick/User.h create mode 100644 Juick/User.m diff --git a/Juick.xcodeproj/project.pbxproj b/Juick.xcodeproj/project.pbxproj index 5b1df20..b1a248c 100644 --- a/Juick.xcodeproj/project.pbxproj +++ b/Juick.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ 77A5BDB0189AEB28000F8D9E /* 0.png in Resources */ = {isa = PBXBuildFile; fileRef = 77A5BDAF189AEB28000F8D9E /* 0.png */; }; 77B09994189D0B9900A84F59 /* UIImage+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 77B09993189D0B9900A84F59 /* UIImage+Utils.m */; }; 77B099A3189D516800A84F59 /* UILabel+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 77B099A2189D516800A84F59 /* UILabel+Utils.m */; }; + 77B099A6189D57F000A84F59 /* User.m in Sources */ = {isa = PBXBuildFile; fileRef = 77B099A5189D57F000A84F59 /* User.m */; }; + 77B099A9189D61BB00A84F59 /* TitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 77B099A8189D61BB00A84F59 /* TitleView.m */; }; 77C67EDE182827DB00427098 /* reveal-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 77C67EDC182827DB00427098 /* reveal-icon.png */; }; 77C67EDF182827DB00427098 /* reveal-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 77C67EDD182827DB00427098 /* reveal-icon@2x.png */; }; 77C67EE21828288C00427098 /* RevealPanelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 77C67EE11828288C00427098 /* RevealPanelViewController.m */; }; @@ -90,6 +92,10 @@ 77B09993189D0B9900A84F59 /* UIImage+Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Utils.m"; sourceTree = ""; }; 77B099A1189D516800A84F59 /* UILabel+Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UILabel+Utils.h"; sourceTree = ""; }; 77B099A2189D516800A84F59 /* UILabel+Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UILabel+Utils.m"; sourceTree = ""; }; + 77B099A4189D57F000A84F59 /* User.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = User.h; sourceTree = ""; }; + 77B099A5189D57F000A84F59 /* User.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = User.m; sourceTree = ""; }; + 77B099A7189D61BB00A84F59 /* TitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TitleView.h; sourceTree = ""; }; + 77B099A8189D61BB00A84F59 /* TitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TitleView.m; sourceTree = ""; }; 77C67EDC182827DB00427098 /* reveal-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "reveal-icon.png"; sourceTree = ""; }; 77C67EDD182827DB00427098 /* reveal-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "reveal-icon@2x.png"; sourceTree = ""; }; 77C67EE01828288C00427098 /* RevealPanelViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RevealPanelViewController.h; sourceTree = ""; }; @@ -209,6 +215,10 @@ 77E35A81189A5B5A00B2D216 /* LoginViewController.m */, 77B09992189D0B9900A84F59 /* UIImage+Utils.h */, 77B09993189D0B9900A84F59 /* UIImage+Utils.m */, + 77B099A4189D57F000A84F59 /* User.h */, + 77B099A5189D57F000A84F59 /* User.m */, + 77B099A7189D61BB00A84F59 /* TitleView.h */, + 77B099A8189D61BB00A84F59 /* TitleView.m */, ); path = Juick; sourceTree = ""; @@ -390,7 +400,9 @@ 771E4AD618606AA400EBACC8 /* NavCell.m in Sources */, 77B099A3189D516800A84F59 /* UILabel+Utils.m in Sources */, 77317BC2181BBE8500D60005 /* MessagesViewController.m in Sources */, + 77B099A9189D61BB00A84F59 /* TitleView.m in Sources */, 77C67EE21828288C00427098 /* RevealPanelViewController.m in Sources */, + 77B099A6189D57F000A84F59 /* User.m in Sources */, 77975A1D182B6E9A00410C2B /* NewPostViewController.m in Sources */, 77C67EE81828379700427098 /* ColorScheme.m in Sources */, 77C67EE51828342000427098 /* NSURL+PathParameters.m in Sources */, diff --git a/Juick/AppDelegate.h b/Juick/AppDelegate.h index 0b1fbb7..561f7ee 100644 --- a/Juick/AppDelegate.h +++ b/Juick/AppDelegate.h @@ -7,6 +7,8 @@ // #import +#import "User.h" +#import "TitleView.h" @class SWRevealViewController; diff --git a/Juick/AppDelegate.m b/Juick/AppDelegate.m index 779de12..7c90018 100644 --- a/Juick/AppDelegate.m +++ b/Juick/AppDelegate.m @@ -57,8 +57,18 @@ split.delegate = messages; self.viewController = split; } - [messages loadFromPath:[Message messagesUrl] withParams:nil withTitle:@"Discover"]; - + if ([User isAuthenticated]) { + [User checkIsValid:^(BOOL success) { + if (success) { + [messages loadFromPath:[Message feedUrl] withParams:nil withTitle:@"My feed"]; + } else { + [User throwUnableToLogin]; + } + }]; + + } else { + [messages loadFromPath:[Message messagesUrl] withParams:nil withTitle:@"Discover"]; + } self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; diff --git a/Juick/LoginViewController.m b/Juick/LoginViewController.m index 7a4dbca..366ec96 100644 --- a/Juick/LoginViewController.m +++ b/Juick/LoginViewController.m @@ -7,6 +7,7 @@ // #import "LoginViewController.h" +#import "User.h" @implementation LoginViewController @@ -32,13 +33,20 @@ static NSString *CellIdentifier = @"CellIdentifier"; } - (void) doneSignIn { - CATransition* transition = [CATransition animation]; - transition.duration = 0.3; - transition.type = kCATransitionFade; - transition.subtype = kCATransitionFromTop; + [User checkIsValid:^(BOOL success) { + if (success) { + CATransition* transition = [CATransition animation]; + transition.duration = 0.3; + transition.type = kCATransitionFade; + transition.subtype = kCATransitionFromTop; + + [self.navigationController.view.layer addAnimation:transition forKey:kCATransition]; + [self.navigationController popToRootViewControllerAnimated:NO]; + } else { + [User throwUnableToLogin]; + } + }]; - [self.navigationController.view.layer addAnimation:transition forKey:kCATransition]; - [self.navigationController popToRootViewControllerAnimated:NO]; } -(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { diff --git a/Juick/RevealPanelViewController.h b/Juick/RevealPanelViewController.h index 812c6f7..89f87e9 100644 --- a/Juick/RevealPanelViewController.h +++ b/Juick/RevealPanelViewController.h @@ -9,7 +9,11 @@ #import #import #import "LoginViewController.h" +#import "TitleView.h" +#import -@interface RevealPanelViewController : UITableViewController - +@interface RevealPanelViewController : UIViewController +@property (nonatomic, strong) IBOutlet UITableView *tableView; +@property (nonatomic, strong) IBOutlet UIButton *signButton; +@property(nonatomic, strong) IBOutlet TitleView *titleView; @end diff --git a/Juick/RevealPanelViewController.m b/Juick/RevealPanelViewController.m index 9d27608..563e06d 100644 --- a/Juick/RevealPanelViewController.m +++ b/Juick/RevealPanelViewController.m @@ -15,7 +15,7 @@ #import "NSURL+PathParameters.h" #import "NavCell.h" #import "Message.h" - +#import "User.h" static NSString *CellIdentifier = @"NavCell"; @@ -38,15 +38,57 @@ static NSString *CellIdentifier = @"NavCell"; - (void)viewDidLoad { [super viewDidLoad]; - self.title = @"Juick"; - + if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1) { self.navigationController.navigationBar.tintColor = [ColorScheme navbarBackground]; } [self.view setBackgroundColor:[ColorScheme navbarBackground]]; + self.tableView = [[UITableView alloc] init]; + [self.tableView setBackgroundColor:[ColorScheme navbarBackground]]; + self.tableView.delegate = self; + self.tableView.dataSource = self; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.tableView.separatorColor =[UIColor blackColor]; [self.tableView registerClass:[NavCell class] forCellReuseIdentifier:CellIdentifier]; + [self.view addSubview:self.tableView]; + self.signButton = [[UIButton alloc] init]; + [self.signButton addTarget:self action:@selector(signInOut) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:self.signButton]; + self.titleView = [[TitleView alloc] initWithImage:nil title:@"Juick"]; + [self.navigationItem setTitleView:self.titleView]; + [self refreshInfo]; +} + +-(void) refreshInfo { + NSString *text; + UIColor *color; + + if ([User isAuthenticated]) { + text = @"Sign Out"; + color = [UIColor redColor]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + [User get:[[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.username"] callback:^(User *user) { + [self.titleView.image setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://i.juick.com/as/%@.png", user.uid]]]; + [self.titleView.title setText:user.uname]; + }]; + }); + } else { + text = @"Sign In"; + color = [UIColor greenColor]; + } + [self.signButton setTitle:text forState:UIControlStateNormal]; + [self.signButton setBackgroundColor:color]; +} + +-(void) signInOut { + [self refreshInfo]; + [self pushLoginForm]; +} + +-(void) viewWillLayoutSubviews { + [super viewWillLayoutSubviews]; + self.tableView.frame = CGRectMake(0, 0, self.view.bounds.size.width, 400); + self.signButton.frame = CGRectMake(0, self.view.bounds.size.height - 40, self.view.bounds.size.width, 40); } - (void)didReceiveMemoryWarning @@ -98,6 +140,13 @@ static NSString *CellIdentifier = @"NavCell"; return cell; } +- (void) pushLoginForm { + [self.revealViewController revealToggle:self]; + UIViewController *loginView = [[LoginViewController alloc] initWithStyle:UITableViewStyleGrouped]; + UINavigationController *messages = (UINavigationController *)self.revealViewController.frontViewController; + [messages pushViewController:loginView animated:YES]; +} + - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger row = indexPath.row; NSString *targetPath; @@ -105,10 +154,7 @@ static NSString *CellIdentifier = @"NavCell"; NSString *targetTitle; if (row == 0) { if ([[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.username"] == nil) { - [self.revealViewController revealToggle:self]; - UIViewController *loginView = [[LoginViewController alloc] initWithStyle:UITableViewStyleGrouped]; - UINavigationController *messages = (UINavigationController *)self.revealViewController.frontViewController; - [messages pushViewController:loginView animated:YES]; + [self pushLoginForm]; return; } else { targetTitle = @"My feed"; diff --git a/Juick/TitleView.h b/Juick/TitleView.h new file mode 100644 index 0000000..17288ef --- /dev/null +++ b/Juick/TitleView.h @@ -0,0 +1,19 @@ +// +// TitleView.h +// Juick +// +// Created by Vitaly on 01.02.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import +#import "UILabel+Utils.h" +#import "ColorScheme.h" + +@interface TitleView : UIView +@property (nonatomic, strong) IBOutlet UIImageView *image; +@property (nonatomic, strong) IBOutlet UILabel *title; + +-(id) initWithImage:(UIImage *) image title:(NSString *)title; + +@end diff --git a/Juick/TitleView.m b/Juick/TitleView.m new file mode 100644 index 0000000..3948041 --- /dev/null +++ b/Juick/TitleView.m @@ -0,0 +1,37 @@ +// +// TitleView.m +// Juick +// +// Created by Vitaly on 01.02.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import "TitleView.h" + +@implementation TitleView + +-(id) initWithImage:(UIImage *)image title:(NSString *)title { + self = [super initWithFrame:CGRectMake(0, 0, 300.0f, 52.0f)]; + if (self) { + self.image = [[UIImageView alloc] init]; + self.image.image = image; + self.title = [[UILabel alloc] init]; + self.title.numberOfLines = 1; + self.title.textAlignment = NSTextAlignmentLeft; + self.title.text = title; + self.title.textColor = [ColorScheme navbarFont]; + [self addSubview:self.image]; + [self addSubview:self.title]; + } + return self; +} + +-(void) layoutSubviews { + [super layoutSubviews]; + self.image.frame = CGRectMake(10, 10, 32, 32); + float textHeight = [UILabel sizeForLabel:self.title width:320.0f].size.height; + self.title.frame = CGRectMake(10 + 32 + 10, 10 + (32 - textHeight) / 2, + self.bounds.size.width - 32 - 10*3, textHeight); +} + +@end diff --git a/Juick/User.h b/Juick/User.h new file mode 100644 index 0000000..e4c46f3 --- /dev/null +++ b/Juick/User.h @@ -0,0 +1,24 @@ +// +// User.h +// Juick +// +// Created by Vitaly on 01.02.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import +#import + +@interface User : NSObject +@property (nonatomic, strong) NSString *uname; +@property (nonatomic, strong) NSString *uid; + ++ (void) get:(NSString *)name callback:(void(^)(User *))callback; + ++ (BOOL) isAuthenticated; + ++ (void) checkIsValid:(void(^)(BOOL))callback; + ++ (void) throwUnableToLogin; + +@end diff --git a/Juick/User.m b/Juick/User.m new file mode 100644 index 0000000..6f1678a --- /dev/null +++ b/Juick/User.m @@ -0,0 +1,67 @@ +// +// User.m +// Juick +// +// Created by Vitaly on 01.02.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import "User.h" +#import "PDKeychainBindings.h" + +@implementation User + ++(BOOL) isAuthenticated { + return [[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.username"] != nil; +} + ++(void) throwUnableToLogin { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Unable to login, check username/password, or network connectivity" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; + [alert show]; +} + ++(void) checkIsValid:(void (^)(BOOL))callback { + RKObjectManager *manager = [RKObjectManager sharedManager]; + [manager.HTTPClient setAuthorizationHeaderWithUsername:[[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.username"] password:[[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.password"]]; + NSURLRequest *request = [[RKObjectManager sharedManager] requestWithObject:nil method:RKRequestMethodPOST path:@"/post" parameters:nil]; + RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[User class]]; + + RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:nil]; + + RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request + responseDescriptors:@[responseDescriptor]]; + [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { + // this will never happens + } failure:^(RKObjectRequestOperation *operation, NSError *error) { + if (operation.HTTPRequestOperation.response.statusCode == 400) { + callback(YES); + } else { + callback(NO); + } + }]; + [operation start]; + +} + ++(void) get:(NSString *) name callback:(void(^)(User *))callback { + RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[User class]]; + [mapping addAttributeMappingsFromDictionary:@ + { + @"uname": @"uname", + @"uid" : @"uid", + }]; + NSString *path = @"/users"; + NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:name, @"uname", nil]; + RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:nil]; + NSURLRequest *request = [[RKObjectManager sharedManager] requestWithObject:nil method:RKRequestMethodGET path:path parameters:params]; + RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request + responseDescriptors:@[responseDescriptor]]; + [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { + callback([[mappingResult array] firstObject]); + } failure:^(RKObjectRequestOperation *operation, NSError *error) { + NSLog(@"REST Error: %@", error); + }]; + [operation start]; +} + +@end -- cgit v1.2.3