From 63f9e9576991fa8e50ca728836c6ba6917bbbc26 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 30 Jan 2014 17:16:06 +0400 Subject: LoginView --- Juick.xcodeproj/project.pbxproj | 6 +++ Juick/AppDelegate.m | 8 +++- Juick/Juick-Info.plist | 4 +- Juick/LoginViewController.h | 18 ++++++++ Juick/LoginViewController.m | 89 +++++++++++++++++++++++++++++++++++++++ Juick/Message.h | 3 +- Juick/Message.m | 13 +++++- Juick/MessagesViewController.h | 2 +- Juick/MessagesViewController.m | 26 ++++++++---- Juick/RevealPanelViewController.h | 1 + Juick/RevealPanelViewController.m | 27 +++++++++--- Podfile | 1 + Podfile.lock | 3 ++ 13 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 Juick/LoginViewController.h create mode 100644 Juick/LoginViewController.m diff --git a/Juick.xcodeproj/project.pbxproj b/Juick.xcodeproj/project.pbxproj index 8248215..7670910 100644 --- a/Juick.xcodeproj/project.pbxproj +++ b/Juick.xcodeproj/project.pbxproj @@ -38,6 +38,7 @@ 77C67EEA18283C8D00427098 /* buttons.png in Resources */ = {isa = PBXBuildFile; fileRef = 77C67EE918283C8D00427098 /* buttons.png */; }; 77C67EEC18283F2D00427098 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77C67EEB18283F2D00427098 /* QuartzCore.framework */; }; 77D163C2181F048F00401EF0 /* MessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 77D163C1181F048F00401EF0 /* MessageCell.m */; }; + 77E35A82189A5B5A00B2D216 /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E35A81189A5B5A00B2D216 /* LoginViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -93,6 +94,8 @@ 77C67EEB18283F2D00427098 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 77D163C0181F048F00401EF0 /* MessageCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageCell.h; sourceTree = ""; }; 77D163C1181F048F00401EF0 /* MessageCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessageCell.m; sourceTree = ""; }; + 77E35A80189A5B5A00B2D216 /* LoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = ""; }; + 77E35A81189A5B5A00B2D216 /* LoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = ""; }; AD52EBAFFD6B4395B342F246 /* Pods-Juick.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Juick.xcconfig"; path = "Pods/Pods-Juick.xcconfig"; sourceTree = ""; }; E1A04338EB0146778B4503DC /* libPods-Juick.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Juick.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -191,6 +194,8 @@ 77975A1C182B6E9A00410C2B /* NewPostViewController.m */, 771E4AD418606AA400EBACC8 /* NavCell.h */, 771E4AD518606AA400EBACC8 /* NavCell.m */, + 77E35A80189A5B5A00B2D216 /* LoginViewController.h */, + 77E35A81189A5B5A00B2D216 /* LoginViewController.m */, ); path = Juick; sourceTree = ""; @@ -373,6 +378,7 @@ 77975A1D182B6E9A00410C2B /* NewPostViewController.m in Sources */, 77C67EE81828379700427098 /* ColorScheme.m in Sources */, 77C67EE51828342000427098 /* NSURL+PathParameters.m in Sources */, + 77E35A82189A5B5A00B2D216 /* LoginViewController.m in Sources */, 77317BB8181BBE8500D60005 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Juick/AppDelegate.m b/Juick/AppDelegate.m index 7ccaf13..779de12 100644 --- a/Juick/AppDelegate.m +++ b/Juick/AppDelegate.m @@ -10,6 +10,7 @@ #import "MessagesViewController.h" #import "RevealPanelViewController.h" #import "SWRevealViewController.h" +#import "LoginViewController.h" #import "ColorScheme.h" #import "Message.h" @@ -30,6 +31,11 @@ AFNetworkActivityIndicatorManager.sharedManager.enabled = YES; + NSURL *baseURL = [NSURL URLWithString:@"https://api.juick.com"]; + AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:baseURL]; + RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client]; + [RKObjectManager setSharedManager:objectManager]; + MessagesViewController *messages = [[MessagesViewController alloc] init]; RevealPanelViewController *rear = [[RevealPanelViewController alloc] init]; @@ -51,7 +57,7 @@ split.delegate = messages; self.viewController = split; } - [messages loadFromURL:[NSURL URLWithString:[Message messagesUrl]] withTitle:@"Discover"]; + [messages loadFromPath:[Message messagesUrl] withParams:nil withTitle:@"Discover"]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.rootViewController = self.viewController; diff --git a/Juick/Juick-Info.plist b/Juick/Juick-Info.plist index 33830ba..374a02f 100644 --- a/Juick/Juick-Info.plist +++ b/Juick/Juick-Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.4 + 1.0.5 CFBundleSignature ???? CFBundleVersion - 1.0.4 + 1.0.5 LSApplicationCategoryType public.app-category.social-networking LSRequiresIPhoneOS diff --git a/Juick/LoginViewController.h b/Juick/LoginViewController.h new file mode 100644 index 0000000..9ebf187 --- /dev/null +++ b/Juick/LoginViewController.h @@ -0,0 +1,18 @@ +// +// LoginViewController.h +// Juick +// +// Created by Vitaly on 30.01.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import +#import "JVFloatLabeledTextField.h" +#import "PDKeychainbindingsController.h" + +@interface LoginViewController : UITableViewController + +@property(nonatomic, strong) JVFloatLabeledTextField *usernameField; +@property(nonatomic, strong) JVFloatLabeledTextField *passwordField; + +@end diff --git a/Juick/LoginViewController.m b/Juick/LoginViewController.m new file mode 100644 index 0000000..7a4dbca --- /dev/null +++ b/Juick/LoginViewController.m @@ -0,0 +1,89 @@ +// +// LoginViewController.m +// Juick +// +// Created by Vitaly on 30.01.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import "LoginViewController.h" + +@implementation LoginViewController + +static NSString *CellIdentifier = @"CellIdentifier"; + +-(void) viewDidLoad { + self.title = @"Sign in"; + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self action:@selector(cancelSignIn)]; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave + target:self action:@selector(doneSignIn)]; +} + + +- (void) cancelSignIn { + CATransition* transition = [CATransition animation]; + transition.duration = 0.3; + transition.type = kCATransitionFade; + transition.subtype = kCATransitionFromTop; + + [self.navigationController.view.layer addAnimation:transition forKey:kCATransition]; + [self.navigationController popViewControllerAnimated:NO]; +} + +- (void) doneSignIn { + 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]; +} + +-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + NSString *key; + if (textField.tag == 0) { + // username change + key = @"com.juick.username"; + } else { + key = @"com.juick.password"; + } + [[PDKeychainBindings sharedKeychainBindings] setObject:[textField.text stringByReplacingCharactersInRange:range withString:string] forKey:key]; + return YES; +} + +- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 2; +} + +-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + } + JVFloatLabeledTextField *textField = [[JVFloatLabeledTextField alloc] init]; + textField.tag = indexPath.row; + textField.delegate = self; + if (indexPath.row == 0) { + textField.floatingLabel.text = @"Username"; + textField.placeholder = @"Username"; + textField.text = [[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.username"]; + } else { + textField.floatingLabel.text = @"Password"; + textField.placeholder = @"Password"; + textField.secureTextEntry = YES; + textField.text = [[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.password"]; + } + [cell.contentView addSubview:textField]; + [textField makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(cell.contentView).with.insets(UIEdgeInsetsMake(5, 25, 5, 25)); + }]; + return cell; +} + +@end diff --git a/Juick/Message.h b/Juick/Message.h index 51541a7..3bbb731 100644 --- a/Juick/Message.h +++ b/Juick/Message.h @@ -22,8 +22,9 @@ @property(nonatomic, copy) NSString *repliesBy; @property(nonatomic, copy) NSDecimalNumber *repliesCount; -+(void) pullNextFromURL:(NSURL *)url callback:(void(^)(NSArray *))callback; ++(void) pullNextFromPath:(NSString *)path params:(NSDictionary *)params callback:(void(^)(NSArray *))callback; +(NSString *) messagesUrl; +(NSString *) threadUrl; ++(NSString *) feedUrl; @end diff --git a/Juick/Message.m b/Juick/Message.m index 70d483c..5ba12d2 100644 --- a/Juick/Message.m +++ b/Juick/Message.m @@ -7,11 +7,16 @@ // #import "Message.h" +#import "PDKeychainBindings.h" @implementation Message -+(void) pullNextFromURL:(NSURL *)url callback:(void(^)(NSArray *))callback { ++(void) pullNextFromPath:(NSString *)path params:(NSDictionary *) params callback:(void(^)(NSArray *))callback { + if ([[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.username"] != nil) { + RKObjectManager *manager = [RKObjectManager sharedManager]; + [manager.HTTPClient setAuthorizationHeaderWithUsername:[[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.username"] password:[[PDKeychainBindings sharedKeychainBindings] stringForKey:@"com.juick.password"]]; + } RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Message class]]; [mapping addAttributeMappingsFromDictionary:@ { @@ -28,7 +33,7 @@ }]; RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:nil]; - NSURLRequest *request = [NSURLRequest requestWithURL:url]; + 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) { @@ -47,4 +52,8 @@ return @"https://api.juick.com/thread"; } ++(NSString *) feedUrl { + return @"https://api.juick.com/home"; +} + @end diff --git a/Juick/MessagesViewController.h b/Juick/MessagesViewController.h index 3e6af7e..bbf4a7e 100644 --- a/Juick/MessagesViewController.h +++ b/Juick/MessagesViewController.h @@ -9,7 +9,7 @@ #import @interface MessagesViewController : UITableViewController -- (void)loadFromURL:(NSURL *)messagesURL withTitle:(NSString *)title; +- (void)loadFromPath:(NSString *)messagesPath withParams:(NSDictionary *)params withTitle:(NSString *)title; - (void) refreshData:(UIRefreshControl *)refresh; - (void) composePressed; @end diff --git a/Juick/MessagesViewController.m b/Juick/MessagesViewController.m index b77901b..4518686 100644 --- a/Juick/MessagesViewController.m +++ b/Juick/MessagesViewController.m @@ -25,15 +25,17 @@ static NSString *CellIdentifier = @"MessageCell"; @property(nonatomic, strong) NSMutableArray *messages; @property(nonatomic, assign) Boolean dataLoading; -@property(nonatomic, strong) NSURL *url; +@property(nonatomic, strong) NSString *path; +@property(nonatomic, strong) NSMutableDictionary *params; @end @implementation MessagesViewController -- (void)loadFromURL:(NSURL *)messagesURL withTitle:(NSString *)title +- (void)loadFromPath:(NSString *)messagesPath withParams:(NSDictionary *)params withTitle:(NSString *)title { - [self setUrl:messagesURL]; + [self setPath:messagesPath]; + [self setParams:params]; self.title = title; [self refreshData:nil]; } @@ -41,7 +43,7 @@ static NSString *CellIdentifier = @"MessageCell"; - (void) refreshData:(UIRefreshControl *)refresh { [self.messages removeAllObjects]; [self.tableView reloadData]; - [Message pullNextFromURL:self.url callback:^(NSArray *next) { + [Message pullNextFromPath:self.path params:self.params callback:^(NSArray *next) { [self.messages addObjectsFromArray:next]; [self.tableView reloadData]; [refresh endRefreshing]; @@ -54,7 +56,7 @@ static NSString *CellIdentifier = @"MessageCell"; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - if ([self.url.absoluteString hasPrefix:[Message threadUrl]]) { + if ([self.path isEqualToString:[Message threadUrl]]) { return; } CGPoint pos = scrollView.contentOffset; @@ -62,9 +64,15 @@ static NSString *CellIdentifier = @"MessageCell"; if (pos.y >= contentHeight && !self.dataLoading) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ self.dataLoading = YES; + if (self.params == nil) { + self.params = [[NSMutableDictionary alloc] init]; + } + Message * lastMessage = [self.messages lastObject]; - NSURL *beforeUrl = [self.url URLByAppendingParameters:[NSDictionary dictionaryWithObjectsAndKeys:lastMessage.MID, @"before_mid", nil]]; - [Message pullNextFromURL:beforeUrl callback:^(NSArray *next) { + if (lastMessage != nil) { + [self.params setValue:lastMessage.MID forKey:@"before_mid"]; + } + [Message pullNextFromPath:self.path params:self.params callback:^(NSArray *next) { dispatch_async(dispatch_get_main_queue(), ^{ [self.messages addObjectsFromArray:next]; [self.tableView reloadData]; @@ -185,11 +193,11 @@ static NSString *CellIdentifier = @"MessageCell"; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if ([self.url.absoluteString hasPrefix:[Message threadUrl]]) + if ([self.path isEqualToString:[Message threadUrl]]) return; Message *msg = [_messages objectAtIndex:indexPath.row]; MessagesViewController *threadViewController = [[MessagesViewController alloc] init]; - [threadViewController loadFromURL:[[NSURL URLWithString:[Message threadUrl]] URLByAppendingParameters:[NSDictionary dictionaryWithObjectsAndKeys:msg.MID, @"mid", nil]] withTitle:@"Thread"]; + [threadViewController loadFromPath:[Message threadUrl] withParams:[NSDictionary dictionaryWithObjectsAndKeys:msg.MID, @"mid", nil] withTitle:@"Thread"]; [self.navigationController pushViewController:threadViewController animated:NO]; } diff --git a/Juick/RevealPanelViewController.h b/Juick/RevealPanelViewController.h index 5a90b99..812c6f7 100644 --- a/Juick/RevealPanelViewController.h +++ b/Juick/RevealPanelViewController.h @@ -8,6 +8,7 @@ #import #import +#import "LoginViewController.h" @interface RevealPanelViewController : UITableViewController diff --git a/Juick/RevealPanelViewController.m b/Juick/RevealPanelViewController.m index a9c71e8..c39c6cd 100644 --- a/Juick/RevealPanelViewController.m +++ b/Juick/RevealPanelViewController.m @@ -14,6 +14,7 @@ #import "ColorScheme.h" #import "NSURL+PathParameters.h" #import "NavCell.h" +#import "Message.h" @@ -95,23 +96,39 @@ static NSString *CellIdentifier = @"NavCell"; - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger row = indexPath.row; - NSURL *targetUrl; + NSString *targetPath; + NSDictionary *targetParams; 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]; + return; + } else { + targetTitle = @"My feed"; + targetPath = [Message feedUrl]; + } + + } if (row == 1) { targetTitle = @"Popular"; - targetUrl = [[NSURL URLWithString:@"https://api.juick.com/messages"] URLByAppendingParameters:[NSDictionary dictionaryWithObjectsAndKeys:@"1", @"popular", nil]]; + targetPath = [Message messagesUrl]; + targetParams = [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"popular", nil]; } else if (row == 2) { targetTitle = @"Discover"; - targetUrl = [NSURL URLWithString:@"https://api.juick.com/messages"]; + targetPath = [Message messagesUrl]; } if (row == 3) { targetTitle = @"Images"; - targetUrl = [[NSURL URLWithString:@"https://api.juick.com/messages"] URLByAppendingParameters:[NSDictionary dictionaryWithObjectsAndKeys:@"photo", @"media", nil]]; + targetPath = [Message messagesUrl]; + targetParams = [NSDictionary dictionaryWithObjectsAndKeys:@"photo", @"media", nil]; } SWRevealViewController *reveal = self.revealViewController; UINavigationController *front = (UINavigationController *)reveal.frontViewController; MessagesViewController *messages = (MessagesViewController *)[front.viewControllers objectAtIndex:0]; - [messages loadFromURL:targetUrl withTitle:targetTitle]; + [messages loadFromPath:targetPath withParams:targetParams withTitle:targetTitle]; [reveal revealToggle:self]; } diff --git a/Podfile b/Podfile index b353595..15820fc 100644 --- a/Podfile +++ b/Podfile @@ -11,6 +11,7 @@ pod 'RestKit' pod 'SDWebImage' pod 'FontAwesome+iOS' pod 'NSDate+TimeAgo' +pod 'JVFloatLabeledTextField' end target "JuickTests" do diff --git a/Podfile.lock b/Podfile.lock index f07eada..2aae0af 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -3,6 +3,7 @@ PODS: - FontAwesome+iOS (0.1.1) - ISO8601DateFormatterValueTransformer (0.5.0): - RKValueTransformers (~> 1.0.0) + - JVFloatLabeledTextField (0.0.5) - Masonry (0.2.4) - MWFeedParser (0.0.1): - MWFeedParser/Feed @@ -44,6 +45,7 @@ PODS: DEPENDENCIES: - FontAwesome+iOS + - JVFloatLabeledTextField - Masonry - MWFeedParser - NSDate+TimeAgo @@ -57,6 +59,7 @@ SPEC CHECKSUMS: AFNetworking: 61fdd49e2ffe6380378df37b3b6e70630bb9dd66 FontAwesome+iOS: 243c5309e90d5788909b0f859f75ecff4a20f88f ISO8601DateFormatterValueTransformer: d0af1f50a9df42db72d7418db31938b8473e0af8 + JVFloatLabeledTextField: 7daac42f450476dc9cfa5b23645e8661b868994b Masonry: 73df2f346bd1a0044dc9de969aa45aea2f8a9bd8 MWFeedParser: 2ca0852fac352f8333d5f46fdd4b583b921e0c4e NSDate+TimeAgo: fe93d3042e83093ae3630bc47ae7d57f782733f6 -- cgit v1.2.3