mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
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:
commit
ac0fa76af4
9 changed files with 113 additions and 65 deletions
|
@ -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
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
- (void) clearFinishedRequests;
|
||||
- (void) cancelRequests;
|
||||
|
||||
- (void)informError:(NSError *)error;
|
||||
- (void)informError:(id)error;
|
||||
|
||||
@end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue