Merge branch 'master' of github.com:samuelclay/NewsBlur

* 'master' of github.com:samuelclay/NewsBlur:
  Last few touch-ups for iPhone app v1.2. Almost ready to send to the app store. Need to design and build a website to finally launch this damn thing.
  Fixing a number of API call parameters.
  Handling server errors (500 errors) in iOS app. Also cancelling requests if switching to a new feed before old feed comes back.
  Adding an Everything folder name to iOS app. Kinda ugly, kinda beautiful.
This commit is contained in:
Samuel Clay 2011-11-30 21:05:13 -08:00
commit ac0fa76af4
9 changed files with 113 additions and 65 deletions

View file

@ -344,7 +344,7 @@ def load_single_feed(request, feed_id):
page = int(request.REQUEST.get('page', 1))
dupe_feed_id = None
userstories_db = None
if page: offset = limit * (page-1)
if not feed_id: raise Http404
@ -742,7 +742,6 @@ def mark_story_as_unread(request):
@ajax_login_required
@json.json_view
def mark_feed_as_read(request):
print request.REQUEST
feed_ids = [int(f) for f in request.REQUEST.getlist('feed_id') if f]
feed_count = len(feed_ids)
multiple = feed_count > 1
@ -833,7 +832,7 @@ def delete_feed(request):
@ajax_login_required
@json.json_view
def delete_folder(request):
folder_to_delete = request.POST['folder_name']
folder_to_delete = request.POST.get('folder_name') or request.POST.get('folder_to_delete')
in_folder = request.POST.get('in_folder', '')
feed_ids_in_folder = [int(f) for f in request.REQUEST.getlist('feed_id') if f]
@ -862,17 +861,21 @@ def rename_feed(request):
@ajax_login_required
@json.json_view
def rename_folder(request):
folder_to_rename = request.POST['folder_name']
folder_to_rename = request.POST.get('folder_name') or request.POST.get('folder_to_rename')
new_folder_name = request.POST['new_folder_name']
in_folder = request.POST.get('in_folder', '')
code = 0
# Works piss poor with duplicate folder titles, if they are both in the same folder.
# renames all, but only in the same folder parent. But nobody should be doing that, right?
if new_folder_name:
if folder_to_rename and new_folder_name:
user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user)
user_sub_folders.rename_folder(folder_to_rename, new_folder_name, in_folder)
return dict(code=1)
code = 1
else:
code = -1
return dict(code=code)
@ajax_login_required
@json.json_view

View file

@ -15,6 +15,6 @@
- (void) clearFinishedRequests;
- (void) cancelRequests;
- (void)informError:(NSError *)error;
- (void)informError:(id)error;
@end

View file

@ -53,15 +53,27 @@
#pragma mark -
#pragma mark View methods
- (void)informError:(NSError *)error {
NSString* localizedDescription = [error localizedDescription];
- (void)informError:(id)error {
NSLog(@"Error: %@", error);
NSString *errorMessage;
if ([error isKindOfClass:[NSString class]]) {
errorMessage = error;
} else {
errorMessage = [error localizedDescription];
if ([error code] == 4 &&
[errorMessage rangeOfString:@"cancelled"].location != NSNotFound) {
return;
}
}
[MBProgressHUD hideHUDForView:self.view animated:YES];
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
[HUD setCustomView:[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"warning.gif"]] autorelease]];
[HUD setCustomView:[[[UIImageView alloc]
initWithImage:[UIImage imageNamed:@"warning.gif"]] autorelease]];
[HUD setMode:MBProgressHUDModeCustomView];
HUD.labelText = localizedDescription;
HUD.labelText = errorMessage;
[HUD hide:YES afterDelay:1];
// UIAlertView* alertView = [[UIAlertView alloc]
// initWithTitle:@"Error"
// message:localizedDescription delegate:nil

View file

@ -37,7 +37,6 @@
- (void)fetchFeedDetail:(int)page withCallback:(void(^)())callback;
- (void)fetchRiverPage:(int)page withCallback:(void(^)())callback;
- (void)finishedLoadingFeed:(ASIHTTPRequest *)request;
- (void)failLoadingFeed:(ASIHTTPRequest *)request;
- (void)renderStories:(NSArray *)newStories;
- (void)scrollViewDidScroll:(UIScrollView *)scroll;

View file

@ -172,14 +172,14 @@
NEWSBLUR_URL,
[appDelegate.activeFeed objectForKey:@"id"],
self.feedPage];
NSURL *urlFeedDetail = [NSURL URLWithString:theFeedDetailURL];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:urlFeedDetail];
[self cancelRequests];
__block ASIHTTPRequest *request = [self requestWithURL:theFeedDetailURL];
[request setDelegate:self];
[request setResponseEncoding:NSUTF8StringEncoding];
[request setDefaultResponseEncoding:NSUTF8StringEncoding];
[request setFailedBlock:^(void) {
[self failLoadingFeed:request];
[self informError:[request error]];
}];
[request setCompletionBlock:^(void) {
[self finishedLoadingFeed:request];
@ -193,22 +193,23 @@
}
}
- (void)failLoadingFeed:(ASIHTTPRequest *)request {
// if (self.feedPage <= 1) {
// [appDelegate.navigationController
// popToViewController:[appDelegate.navigationController.viewControllers
// objectAtIndex:0]
// animated:YES];
// }
[self informError:[request error]];
}
- (void)finishedLoadingFeed:(ASIHTTPRequest *)request {
if ([request responseStatusCode] >= 500) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.15 * NSEC_PER_SEC),
dispatch_get_current_queue(), ^{
[appDelegate.navigationController
popToViewController:[appDelegate.navigationController.viewControllers
objectAtIndex:0]
animated:YES];
});
[self informError:@"The server barfed!"];
return;
}
NSString *responseString = [request responseString];
NSDictionary *results = [[NSDictionary alloc]
initWithDictionary:[responseString JSONValue]];
if (!appDelegate.isRiverView && request.tag != [[results objectForKey:@"feed_id"] intValue]) {
[results release];
return;
@ -261,14 +262,14 @@
[appDelegate.activeFolderFeeds componentsJoinedByString:@"&feeds="],
self.feedPage,
readStoriesCount];
NSURL *urlFeedDetail = [NSURL URLWithString:theFeedDetailURL];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:urlFeedDetail];
[self cancelRequests];
__block ASIHTTPRequest *request = [self requestWithURL:theFeedDetailURL];
[request setDelegate:self];
[request setResponseEncoding:NSUTF8StringEncoding];
[request setDefaultResponseEncoding:NSUTF8StringEncoding];
[request setFailedBlock:^(void) {
[self failLoadingFeed:request];
[self informError:[request error]];
}];
[request setCompletionBlock:^(void) {
[self finishedLoadingFeed:request];
@ -773,7 +774,7 @@
[request addPostValue:[[appDelegate activeFeed] objectForKey:@"id"] forKey:@"feed_id"];
[request addPostValue:[appDelegate activeFolder] forKey:@"in_folder"];
[request setFailedBlock:^(void) {
[self failLoadingFeed:request];
[self informError:[request error]];
}];
[request setCompletionBlock:^(void) {
[appDelegate reloadFeedsView];
@ -797,8 +798,8 @@
stringWithFormat:@"http://%@/reader/refresh_feed/%@",
NEWSBLUR_URL,
[appDelegate.activeFeed objectForKey:@"id"]];
NSURL *url = [NSURL URLWithString:urlString];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[self cancelRequests];
__block ASIHTTPRequest *request = [self requestWithURL:urlString];
[request setDelegate:self];
[request setResponseEncoding:NSUTF8StringEncoding];
[request setDefaultResponseEncoding:NSUTF8StringEncoding];

View file

@ -547,12 +547,14 @@
titleLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:11.0];
titleLabel.shadowOffset = CGSizeMake(0, 1);
if ([[feed objectForKey:@"favicon_text_color"] class] != [NSNull class]) {
titleLabel.textColor = [[feed objectForKey:@"favicon_text_color"] isEqualToString:@"white"] ?
[UIColor whiteColor] :
[UIColor blackColor];
titleLabel.shadowColor = [[feed objectForKey:@"favicon_text_color"] isEqualToString:@"white"] ?
UIColorFromRGB(0x202020):
UIColorFromRGB(0xe0e0e0);
titleLabel.textColor = [[feed objectForKey:@"favicon_text_color"]
isEqualToString:@"white"] ?
[UIColor whiteColor] :
[UIColor blackColor];
titleLabel.shadowColor = [[feed objectForKey:@"favicon_text_color"]
isEqualToString:@"white"] ?
UIColorFromRGB(0x202020) :
UIColorFromRGB(0xd0d0d0);
} else {
titleLabel.textColor = [UIColor whiteColor];
titleLabel.shadowColor = [UIColor blackColor];

View file

@ -47,7 +47,8 @@
- (IBAction)selectIntelligence;
- (void)updateFeedsWithIntelligence:(int)previousLevel newLevel:(int)newLevel;
- (void)calculateFeedLocations:(BOOL)markVisible;
- (IBAction)sectionTapped:(UITapGestureRecognizer *)recognizer;
- (IBAction)sectionTapped:(UIButton *)button;
- (IBAction)sectionUntapped:(UIButton *)button;
- (void)redrawUnreadCounts;
+ (int)computeMaxScoreForFeed:(NSDictionary *)feed;
- (IBAction)doSwitchSitesUnread;

View file

@ -206,7 +206,10 @@
- (void)finishLoadingFeedList:(ASIHTTPRequest *)request {
if ([request responseStatusCode] == 403) {
return [appDelegate showLogin];
return [appDelegate showLogin];
} else if ([request responseStatusCode] >= 500) {
[pull finishedLoading];
return [self informError:@"The server barfed!"];
}
NSString *responseString = [request responseString];
@ -377,7 +380,7 @@
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *FeedCellIdentifier = @"FeedCellIdentifier";
FeedTableCell *cell = (FeedTableCell *)[tableView dequeueReusableCellWithIdentifier:FeedCellIdentifier];
@ -405,7 +408,7 @@
}
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
NSArray *feeds = [appDelegate.dictFolders objectForKey:folderName];
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
@ -428,12 +431,12 @@ didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return kTableViewRowHeight;
}
- (UIView *)tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section {
viewForHeaderInSection:(NSInteger)section {
// create the parent view that will hold header Label
UIControl* customView = [[[UIControl alloc]
initWithFrame:CGRectMake(0.0, 0.0,
@ -450,8 +453,6 @@ viewForHeaderInSection:(NSInteger)section {
[customView addSubview:borderBottom];
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
colorWithAlphaComponent:0.8];
customView.opaque = NO;
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.opaque = NO;
@ -459,9 +460,17 @@ viewForHeaderInSection:(NSInteger)section {
headerLabel.highlightedTextColor = [UIColor whiteColor];
headerLabel.font = [UIFont boldSystemFontOfSize:11];
headerLabel.frame = CGRectMake(36.0, 1.0, 286.0, 20.0);
headerLabel.text = [[appDelegate.dictFoldersArray objectAtIndex:section] uppercaseString];
headerLabel.shadowColor = [UIColor colorWithRed:.94 green:0.94 blue:0.97 alpha:1.0];
headerLabel.shadowOffset = CGSizeMake(1.0, 1.0);
headerLabel.shadowOffset = CGSizeMake(0.0, 1.0);
if (section == 0) {
headerLabel.text = @"EVERYTHING";
customView.backgroundColor = [UIColorFromRGB(0xE6DDD7)
colorWithAlphaComponent:0.8];
} else {
headerLabel.text = [[appDelegate.dictFoldersArray objectAtIndex:section] uppercaseString];
customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
colorWithAlphaComponent:0.8];
}
[customView addSubview:headerLabel];
[headerLabel release];
@ -485,35 +494,56 @@ viewForHeaderInSection:(NSInteger)section {
[customView addSubview:invisibleHeaderButton];
[invisibleHeaderButton addTarget:self action:@selector(sectionTapped:) forControlEvents:UIControlEventTouchDown];
[invisibleHeaderButton addTarget:self action:@selector(sectionUntapped:) forControlEvents:UIControlEventTouchUpInside];
[invisibleHeaderButton addTarget:self action:@selector(sectionUntapped:) forControlEvents:UIControlEventTouchUpOutside];
[customView setAutoresizingMask:UIViewAutoresizingNone];
return customView;
}
- (IBAction)sectionTapped:(UIButton *)button {
button.backgroundColor = [UIColor blackColor];
button.backgroundColor =[UIColor colorWithRed:0.15 green:0.55 blue:0.95 alpha:1.0];
}
- (IBAction)sectionUntapped:(UIButton *)button {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.15 * NSEC_PER_SEC),
dispatch_get_current_queue(), ^{
button.backgroundColor = [UIColor clearColor];
});
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
NSString *folder = [appDelegate.dictFoldersArray objectAtIndex:section];
if ([[folder stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) {
return 0;
}
// NSString *folder = [appDelegate.dictFoldersArray objectAtIndex:section];
// if ([[folder stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) {
// return 0;
// }
return 21;
}
- (void)didSelectSectionHeader:(UIButton *)button {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:button.tag];
[appDelegate setActiveFolder:folderName];
appDelegate.readStories = [NSMutableArray array];
appDelegate.isRiverView = YES;
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
NSMutableArray *feeds = [NSMutableArray array];
for (int l=0; l < [activeFolderFeeds count]; l++) {
[feeds addObject:[originalFolder objectAtIndex:[[activeFolderFeeds objectAtIndex:l] intValue]]];
if (button.tag == 0) {
[appDelegate setActiveFolder:@"Everything"];
for (NSString *folderName in self.activeFeedLocations) {
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
NSArray *folderFeeds = [self.activeFeedLocations objectForKey:folderName];
for (int l=0; l < [folderFeeds count]; l++) {
[feeds addObject:[originalFolder objectAtIndex:[[folderFeeds objectAtIndex:l] intValue]]];
}
}
} else {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:button.tag];
[appDelegate setActiveFolder:folderName];
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
for (int l=0; l < [activeFolderFeeds count]; l++) {
[feeds addObject:[originalFolder objectAtIndex:[[activeFolderFeeds objectAtIndex:l] intValue]]];
}
}
appDelegate.activeFolderFeeds = feeds;

View file

@ -359,7 +359,7 @@
multiple folders.
required: true
example: "Blogs"
- key: in_folder
- key: to_folder
desc: "Folder the feed is going into."
required: true
example: "Tumblrs"
@ -382,7 +382,7 @@
name is in multiple folders. (Please don't let this happen.)
required: true
example: "Blogs"
- key: in_folder
- key: to_folder
desc: "New folder the existing folder is going into."
required: true
example: "Daily Blogs"