2010-06-21 17:17:26 -04:00
|
|
|
//
|
|
|
|
// FeedDetailViewController.m
|
|
|
|
// NewsBlur
|
|
|
|
//
|
|
|
|
// Created by Samuel Clay on 6/20/10.
|
|
|
|
// Copyright 2010 NewsBlur. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "FeedDetailViewController.h"
|
|
|
|
#import "NewsBlurAppDelegate.h"
|
2010-07-15 00:44:38 -04:00
|
|
|
#import "FeedDetailTableCell.h"
|
2010-06-24 00:22:26 -04:00
|
|
|
#import "JSON.h"
|
2010-06-21 17:17:26 -04:00
|
|
|
|
2011-07-20 21:08:57 -07:00
|
|
|
#define kTableViewRowHeight 60;
|
2010-06-21 17:17:26 -04:00
|
|
|
|
|
|
|
@implementation FeedDetailViewController
|
|
|
|
|
2010-11-22 10:44:52 -05:00
|
|
|
@synthesize storyTitlesTable, feedViewToolbar, feedScoreSlider, feedMarkReadButton;
|
2010-06-24 00:22:26 -04:00
|
|
|
@synthesize stories;
|
2010-06-21 17:17:26 -04:00
|
|
|
@synthesize appDelegate;
|
2010-06-24 12:53:50 -04:00
|
|
|
@synthesize jsonString;
|
2011-07-20 22:21:11 -07:00
|
|
|
@synthesize feedPage;
|
|
|
|
@synthesize pageFetching;
|
2010-06-21 17:17:26 -04:00
|
|
|
|
|
|
|
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
|
|
|
|
|
2011-03-09 18:23:55 -05:00
|
|
|
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
|
2010-06-21 17:17:26 -04:00
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2010-06-24 12:53:50 -04:00
|
|
|
- (void)viewWillAppear:(BOOL)animated {
|
2011-07-22 09:10:13 -07:00
|
|
|
// NSLog(@"Loaded Feed view: %@", appDelegate.activeFeed);
|
2010-06-27 19:35:17 -04:00
|
|
|
|
2010-11-13 18:32:43 -05:00
|
|
|
self.title = [appDelegate.activeFeed objectForKey:@"feed_title"];
|
2010-06-24 12:53:50 -04:00
|
|
|
[super viewWillAppear:animated];
|
2010-06-21 17:17:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewDidAppear:(BOOL)animated {
|
2010-06-25 18:36:01 -04:00
|
|
|
//[appDelegate showNavigationBar:animated];
|
2010-11-22 10:44:52 -05:00
|
|
|
[[storyTitlesTable cellForRowAtIndexPath:[storyTitlesTable indexPathForSelectedRow]] setSelected:NO]; // TODO: DESELECT CELL
|
2010-06-21 17:17:26 -04:00
|
|
|
[super viewDidAppear:animated];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)didReceiveMemoryWarning {
|
|
|
|
// Releases the view if it doesn't have a superview.
|
|
|
|
[super didReceiveMemoryWarning];
|
|
|
|
|
|
|
|
// Release any cached data, images, etc that aren't in use.
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewDidUnload {
|
|
|
|
// Release any retained subviews of the main view.
|
|
|
|
// e.g. self.myOutlet = nil;
|
2010-06-24 12:53:50 -04:00
|
|
|
//NSLog(@"Unloading detail view: %@", self);
|
2010-06-24 00:22:26 -04:00
|
|
|
self.appDelegate = nil;
|
2010-06-24 12:53:50 -04:00
|
|
|
self.jsonString = nil;
|
2010-06-21 17:17:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
[appDelegate release];
|
2010-06-24 00:22:26 -04:00
|
|
|
[stories release];
|
2010-06-24 12:53:50 -04:00
|
|
|
[jsonString release];
|
2010-06-21 17:17:26 -04:00
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
2010-06-24 00:22:26 -04:00
|
|
|
#pragma mark Initialization
|
|
|
|
|
2011-07-20 22:21:11 -07:00
|
|
|
- (void)fetchFeedDetail:(int)page {
|
|
|
|
if ([appDelegate.activeFeed objectForKey:@"id"] != nil && !self.pageFetching) {
|
|
|
|
self.feedPage = page;
|
|
|
|
self.pageFetching = YES;
|
2011-07-22 09:10:13 -07:00
|
|
|
if ([appDelegate.activeFeedStories count] == 0) {
|
|
|
|
[storyTitlesTable scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
|
|
|
|
}
|
2011-07-20 21:08:57 -07:00
|
|
|
|
2010-11-22 10:44:52 -05:00
|
|
|
NSString *theFeedDetailURL = [[NSString alloc]
|
2011-07-20 22:21:11 -07:00
|
|
|
initWithFormat:@"http://nb.local.host:8000/reader/feed/%@?page=%d",
|
|
|
|
[appDelegate.activeFeed objectForKey:@"id"],
|
|
|
|
self.feedPage];
|
2010-06-24 12:53:50 -04:00
|
|
|
//NSLog(@"Url: %@", theFeedDetailURL);
|
2010-06-24 00:22:26 -04:00
|
|
|
NSURL *urlFeedDetail = [NSURL URLWithString:theFeedDetailURL];
|
|
|
|
[theFeedDetailURL release];
|
2010-07-15 23:32:37 -04:00
|
|
|
jsonString = [[NSMutableData data] retain];
|
2010-06-24 00:22:26 -04:00
|
|
|
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: urlFeedDetail];
|
|
|
|
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
|
|
|
|
[connection release];
|
|
|
|
[request release];
|
|
|
|
}
|
|
|
|
}
|
2010-06-21 17:17:26 -04:00
|
|
|
|
2010-07-15 23:32:37 -04:00
|
|
|
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
|
|
|
|
{
|
|
|
|
[jsonString setLength:0];
|
|
|
|
}
|
|
|
|
|
2010-06-24 00:22:26 -04:00
|
|
|
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
|
2010-06-24 12:53:50 -04:00
|
|
|
{
|
2010-07-15 23:32:37 -04:00
|
|
|
[jsonString appendData:data];
|
2010-06-24 12:53:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
|
2010-07-15 23:32:37 -04:00
|
|
|
NSString *jsonS = [[NSString alloc]
|
|
|
|
initWithData:jsonString
|
|
|
|
encoding:NSUTF8StringEncoding];
|
2010-06-24 12:53:50 -04:00
|
|
|
NSDictionary *results = [[NSDictionary alloc]
|
2010-07-15 23:32:37 -04:00
|
|
|
initWithDictionary:[jsonS JSONValue]];
|
2011-07-22 09:10:13 -07:00
|
|
|
NSArray *newStories = [results objectForKey:@"stories"];
|
|
|
|
NSUInteger existingStoriesCount = [stories count];
|
|
|
|
|
2011-07-20 22:21:11 -07:00
|
|
|
if (self.feedPage == 1) {
|
2011-07-22 09:10:13 -07:00
|
|
|
[appDelegate setActiveFeedStories:newStories];
|
2011-07-20 22:21:11 -07:00
|
|
|
} else {
|
2011-07-22 09:10:13 -07:00
|
|
|
[appDelegate addActiveFeedStories:newStories];
|
|
|
|
}
|
|
|
|
NSLog(@"Stories: %d on page %d. %d stories already.", [appDelegate.activeFeedStories count], self.feedPage, existingStoriesCount);
|
|
|
|
if (existingStoriesCount > 0) {
|
|
|
|
int endPosition = [newStories count]+existingStoriesCount;
|
|
|
|
NSMutableArray *indexPaths = [NSMutableArray alloc];
|
|
|
|
for (int i=0; i < [newStories count]; i++) {
|
|
|
|
int row = existingStoriesCount+i;
|
|
|
|
[indexPaths addObject:[NSIndexPath indexPathForRow:row inSection:0]];
|
|
|
|
}
|
|
|
|
[self.storyTitlesTable insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
|
|
|
|
[indexPaths release];
|
|
|
|
} else {
|
|
|
|
[self.storyTitlesTable reloadData];
|
2011-07-20 22:21:11 -07:00
|
|
|
}
|
|
|
|
self.pageFetching = NO;
|
2010-06-24 00:22:26 -04:00
|
|
|
[results release];
|
2010-07-15 23:32:37 -04:00
|
|
|
[jsonS release];
|
2010-06-24 00:22:26 -04:00
|
|
|
[jsonString release];
|
2010-06-21 17:17:26 -04:00
|
|
|
}
|
|
|
|
|
2010-07-15 23:32:37 -04:00
|
|
|
- (void)connection:(NSURLConnection *)connection
|
|
|
|
didFailWithError:(NSError *)error
|
|
|
|
{
|
|
|
|
// release the connection, and the data object
|
|
|
|
[connection release];
|
|
|
|
// receivedData is declared as a method instance elsewhere
|
|
|
|
[jsonString release];
|
|
|
|
|
|
|
|
// inform the user
|
2010-11-15 19:40:17 -05:00
|
|
|
NSLog(@"Connection failed! Error - %@",
|
|
|
|
[error localizedDescription]);
|
2011-07-20 22:21:11 -07:00
|
|
|
|
|
|
|
self.pageFetching = NO;
|
2010-07-15 23:32:37 -04:00
|
|
|
}
|
|
|
|
|
2010-06-21 17:17:26 -04:00
|
|
|
|
2010-06-24 00:22:26 -04:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Table View - Feed List
|
2010-06-21 17:17:26 -04:00
|
|
|
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
2010-06-25 18:36:01 -04:00
|
|
|
//NSLog(@"Stories: %d", [appDelegate.activeFeedStories count]);
|
|
|
|
return [appDelegate.activeFeedStories count];
|
2010-06-21 17:17:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
2010-07-15 00:44:38 -04:00
|
|
|
static NSString *FeedDetailCellIdentifier = @"FeedDetailCellIdentifier";
|
2010-06-21 17:17:26 -04:00
|
|
|
|
2010-07-15 00:44:38 -04:00
|
|
|
FeedDetailTableCell *cell = (FeedDetailTableCell *)[tableView dequeueReusableCellWithIdentifier:FeedDetailCellIdentifier];
|
2010-06-21 17:17:26 -04:00
|
|
|
if (cell == nil) {
|
2010-07-15 00:44:38 -04:00
|
|
|
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FeedDetailTableCell"
|
|
|
|
owner:self
|
|
|
|
options:nil];
|
|
|
|
for (id oneObject in nib) {
|
|
|
|
if ([oneObject isKindOfClass:[FeedDetailTableCell class]]) {
|
|
|
|
cell = (FeedDetailTableCell *)oneObject;
|
|
|
|
}
|
|
|
|
}
|
2010-06-21 17:17:26 -04:00
|
|
|
}
|
2010-06-24 00:22:26 -04:00
|
|
|
|
2010-07-15 00:44:38 -04:00
|
|
|
NSDictionary *story = [appDelegate.activeFeedStories objectAtIndex:indexPath.row];
|
|
|
|
if ([[story objectForKey:@"story_authors"] class] != [NSNull class]) {
|
2011-06-13 10:44:17 -04:00
|
|
|
cell.storyAuthor.text = [[story objectForKey:@"story_authors"] uppercaseString];
|
2010-07-15 00:44:38 -04:00
|
|
|
} else {
|
|
|
|
cell.storyAuthor.text = @"";
|
|
|
|
}
|
|
|
|
cell.storyTitle.text = [story objectForKey:@"story_title"];
|
2011-06-13 10:44:17 -04:00
|
|
|
cell.storyDate.text = [story objectForKey:@"short_parsed_date"];
|
2010-11-22 10:44:52 -05:00
|
|
|
|
|
|
|
if ([[story objectForKey:@"read_status"] intValue] != 1) {
|
|
|
|
// Unread story
|
2011-07-20 21:08:57 -07:00
|
|
|
cell.storyTitle.textColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:1.0];
|
|
|
|
cell.storyTitle.font = [UIFont fontWithName:@"Helvetica-Bold" size:12];
|
|
|
|
cell.storyAuthor.textColor = [UIColor colorWithRed:0.58f green:0.58f blue:0.58f alpha:1.0];
|
|
|
|
cell.storyAuthor.font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
|
|
|
|
cell.storyDate.textColor = [UIColor colorWithRed:0.14f green:0.18f blue:0.42f alpha:1.0];
|
|
|
|
cell.storyDate.font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
|
2010-11-22 10:44:52 -05:00
|
|
|
int score = [NewsBlurAppDelegate computeStoryScore:[story objectForKey:@"intelligence"]];
|
|
|
|
if (score > 0) {
|
|
|
|
cell.storyUnreadIndicator.image = [UIImage imageNamed:@"bullet_green.png"];
|
|
|
|
} else if (score == 0) {
|
|
|
|
cell.storyUnreadIndicator.image = [UIImage imageNamed:@"bullet_orange.png"];
|
|
|
|
} else if (score < 0) {
|
|
|
|
cell.storyUnreadIndicator.image = [UIImage imageNamed:@"bullet_red.png"];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Read story
|
2011-07-20 21:08:57 -07:00
|
|
|
cell.storyTitle.textColor = [UIColor colorWithRed:0.15f green:0.25f blue:0.25f alpha:0.9];
|
|
|
|
cell.storyTitle.font = [UIFont fontWithName:@"Helvetica" size:12];
|
|
|
|
cell.storyAuthor.textColor = [UIColor colorWithRed:0.58f green:0.58f blue:0.58f alpha:0.5];
|
|
|
|
cell.storyAuthor.font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
|
|
|
|
cell.storyDate.textColor = [UIColor colorWithRed:0.14f green:0.18f blue:0.42f alpha:0.5];
|
|
|
|
cell.storyDate.font = [UIFont fontWithName:@"Helvetica" size:10];
|
2010-11-22 10:44:52 -05:00
|
|
|
cell.storyUnreadIndicator.image = nil;
|
|
|
|
}
|
2010-07-15 00:44:38 -04:00
|
|
|
|
2010-06-21 17:17:26 -04:00
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
2010-06-25 18:36:01 -04:00
|
|
|
[appDelegate setActiveStory:[[appDelegate activeFeedStories] objectAtIndex:indexPath.row]];
|
|
|
|
[appDelegate loadStoryDetailView];
|
2010-06-21 17:17:26 -04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-07-15 00:44:38 -04:00
|
|
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
return kTableViewRowHeight;
|
|
|
|
}
|
|
|
|
|
2011-07-20 22:21:11 -07:00
|
|
|
- (void)scrollViewDidScroll: (UIScrollView *)scroll {
|
|
|
|
// UITableView only moves in one direction, y axis
|
|
|
|
NSInteger currentOffset = scroll.contentOffset.y;
|
|
|
|
NSInteger maximumOffset = scroll.contentSize.height - scroll.frame.size.height;
|
|
|
|
|
|
|
|
// Change 10.0 to adjust the distance from bottom
|
|
|
|
if (maximumOffset - currentOffset <= 10.0) {
|
|
|
|
[self fetchFeedDetail:self.feedPage+1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-21 17:17:26 -04:00
|
|
|
@end
|