mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
#1723 (some thumbnails not showing on app but do show on the web)
- Changed the preview image caching to try each of the story images in turn until a valid one (not missing or too small) is found. - Only loads one image for each story initially, loading more if needed. - Now caches based on the story hash instead of image URL.
This commit is contained in:
parent
bb721b7b09
commit
7e572477a5
4 changed files with 75 additions and 73 deletions
|
@ -75,8 +75,6 @@
|
|||
- (void)fetchRiver;
|
||||
- (void)fetchRiverPage:(int)page withCallback:(void(^)(void))callback;
|
||||
- (void)testForTryFeed;
|
||||
- (void)cacheStoryImages:(NSArray *)storyImageUrls;
|
||||
- (void)showStoryImage:(NSString *)imageUrl;
|
||||
- (void)flashInfrequentStories;
|
||||
- (void)gotoFolder:(NSString *)folder feedID:(NSString *)feedID;
|
||||
|
||||
|
|
|
@ -700,37 +700,17 @@ typedef NS_ENUM(NSUInteger, MarkReadShowMenu)
|
|||
});
|
||||
}
|
||||
|
||||
- (void)cacheStoryImages:(NSArray *)storyImageUrls {
|
||||
- (void)cacheImagesForStories:(NSArray *)stories {
|
||||
NSBlockOperation *cacheImagesOperation = [NSBlockOperation blockOperationWithBlock:^{
|
||||
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
|
||||
[manager.requestSerializer setTimeoutInterval:5];
|
||||
manager.responseSerializer = [AFImageResponseSerializer serializer];
|
||||
|
||||
for (NSString *storyImageUrl in storyImageUrls) {
|
||||
// NSLog(@"Fetching image: %@", storyImageUrl);
|
||||
[manager GET:storyImageUrl parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0ul);
|
||||
dispatch_async(queue, ^{
|
||||
UIImage *image = (UIImage *)responseObject;
|
||||
|
||||
if (!image || image.size.height < 50 || image.size.width < 50) {
|
||||
[self.appDelegate.cachedStoryImages setObject:[NSNull null]
|
||||
forKey:storyImageUrl];
|
||||
return;
|
||||
}
|
||||
|
||||
CGSize maxImageSize = CGSizeMake(300, 300);
|
||||
image = [image imageByScalingAndCroppingForSize:maxImageSize];
|
||||
[self.appDelegate.cachedStoryImages setObject:image
|
||||
forKey:storyImageUrl];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.appDelegate.feedDetailViewController
|
||||
showStoryImage:storyImageUrl];
|
||||
});
|
||||
});
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
|
||||
}];
|
||||
|
||||
for (NSDictionary *story in stories) {
|
||||
NSString *storyHash = story[@"story_hash"];
|
||||
NSArray *imageURLs = story[@"image_urls"];
|
||||
self.appDelegate.cachedStoryImages[storyHash] = [NSNull null];
|
||||
[self getFirstImage:imageURLs forStoryHash:storyHash withManager:manager];
|
||||
}
|
||||
}];
|
||||
[cacheImagesOperation setQualityOfService:NSQualityOfServiceBackground];
|
||||
|
@ -738,32 +718,67 @@ typedef NS_ENUM(NSUInteger, MarkReadShowMenu)
|
|||
[appDelegate.cacheImagesOperationQueue addOperation:cacheImagesOperation];
|
||||
}
|
||||
|
||||
- (void)showStoryImage:(NSString *)imageUrl {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.view.window == nil) {
|
||||
NSLog(@"showStoryImage when not in a window: %@", imageUrl); // log
|
||||
return;
|
||||
}
|
||||
|
||||
for (FeedDetailTableCell *cell in [self.storyTitlesTable visibleCells]) {
|
||||
if (![cell isKindOfClass:[FeedDetailTableCell class]]) return;
|
||||
if ([cell.storyImageUrl isEqualToString:imageUrl]) {
|
||||
NSIndexPath *indexPath = [self.storyTitlesTable indexPathForCell:cell];
|
||||
NSInteger numberOfRows = [self.storyTitlesTable numberOfRowsInSection:0];
|
||||
|
||||
NSLog(@"showStoryImage for row %@ of %@", @(indexPath.row), @(numberOfRows)); // log
|
||||
|
||||
if (indexPath.row >= numberOfRows) {
|
||||
NSLog(@"⚠️ row %@ is greater than the number of rows: %@", @(indexPath.row), @(numberOfRows)); // log
|
||||
continue;
|
||||
- (void)getFirstImage:(NSArray *)storyImageUrls forStoryHash:(NSString *)storyHash withManager:(AFHTTPSessionManager *)manager {
|
||||
NSString *storyImageUrl = [[storyImageUrls firstObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
|
||||
|
||||
if (storyImageUrl == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[manager GET:storyImageUrl parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0ul);
|
||||
dispatch_async(queue, ^{
|
||||
UIImage *image = (UIImage *)responseObject;
|
||||
|
||||
if (!image || image.size.height < 50 || image.size.width < 50) {
|
||||
if (storyImageUrls.count > 1) {
|
||||
NSArray *remainingImageUrls = [storyImageUrls subarrayWithRange:NSMakeRange(1, storyImageUrls.count - 1)];
|
||||
[self getFirstImage:remainingImageUrls forStoryHash:storyHash withManager:manager];
|
||||
}
|
||||
|
||||
[self.storyTitlesTable reloadRowsAtIndexPaths:@[indexPath]
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
CGSize maxImageSize = CGSizeMake(300, 300);
|
||||
image = [image imageByScalingAndCroppingForSize:maxImageSize];
|
||||
self.appDelegate.cachedStoryImages[storyHash] = image;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self showImageForStoryHash:storyHash];
|
||||
});
|
||||
});
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
NSLog(@"getFirstImage for %@ error: %@", storyHash, error); // log
|
||||
|
||||
if (storyImageUrls.count > 1) {
|
||||
NSArray *remainingImageUrls = [storyImageUrls subarrayWithRange:NSMakeRange(1, storyImageUrls.count - 1)];
|
||||
[self getFirstImage:remainingImageUrls forStoryHash:storyHash withManager:manager];
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)showImageForStoryHash:(NSString *)storyHash {
|
||||
if (self.view.window == nil) {
|
||||
NSLog(@"showImageForStoryHash when not in a window: %@", storyHash); // log
|
||||
return;
|
||||
}
|
||||
|
||||
for (FeedDetailTableCell *cell in [self.storyTitlesTable visibleCells]) {
|
||||
if (![cell isKindOfClass:[FeedDetailTableCell class]]) return;
|
||||
if ([cell.storyHash isEqualToString:storyHash]) {
|
||||
NSIndexPath *indexPath = [self.storyTitlesTable indexPathForCell:cell];
|
||||
NSInteger numberOfRows = [self.storyTitlesTable numberOfRowsInSection:0];
|
||||
|
||||
NSLog(@"showImageForStoryHash for row %@ of %@", @(indexPath.row), @(numberOfRows)); // log
|
||||
|
||||
if (indexPath.row >= numberOfRows) {
|
||||
NSLog(@"⚠️ row %@ is greater than the number of rows: %@", @(indexPath.row), @(numberOfRows)); // log
|
||||
continue;
|
||||
}
|
||||
|
||||
[self.storyTitlesTable reloadRowsAtIndexPaths:@[indexPath]
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)flashInfrequentStories {
|
||||
|
@ -1321,22 +1336,14 @@ typedef NS_ENUM(NSUInteger, MarkReadShowMenu)
|
|||
|
||||
[self.storyTitlesTable reloadData];
|
||||
|
||||
|
||||
if (self.view.window && self.finishedAnimatingIn) {
|
||||
[self testForTryFeed];
|
||||
}
|
||||
|
||||
NSMutableArray *storyImageUrls = [NSMutableArray array];
|
||||
for (NSDictionary *story in newStories) {
|
||||
if ([story objectForKey:@"image_urls"] && [[story objectForKey:@"image_urls"] count]) {
|
||||
[storyImageUrls addObject:[[[story objectForKey:@"image_urls"] objectAtIndex:0]
|
||||
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
|
||||
}
|
||||
}
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0ul);
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC),
|
||||
queue, ^(void) {
|
||||
[self cacheStoryImages:storyImageUrls];
|
||||
[self cacheImagesForStories:newStories];
|
||||
});
|
||||
|
||||
self.pageFetching = NO;
|
||||
|
@ -1619,11 +1626,7 @@ typedef NS_ENUM(NSUInteger, MarkReadShowMenu)
|
|||
cell.storyTimestamp = [[story objectForKey:@"story_timestamp"] integerValue];
|
||||
cell.isSaved = [[story objectForKey:@"starred"] boolValue];
|
||||
cell.isShared = [[story objectForKey:@"shared"] boolValue];
|
||||
cell.storyImageUrl = nil;
|
||||
if (self.showImagePreview &&
|
||||
[story objectForKey:@"image_urls"] && [[story objectForKey:@"image_urls"] count]) {
|
||||
cell.storyImageUrl = [[story objectForKey:@"image_urls"] objectAtIndex:0];
|
||||
}
|
||||
cell.storyHash = story[@"story_hash"];
|
||||
|
||||
if ([[story objectForKey:@"story_authors"] class] != [NSNull class]) {
|
||||
cell.storyAuthor = [[story objectForKey:@"story_authors"] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
|
@ -3044,8 +3047,8 @@ didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state
|
|||
UIImage *storyImage = nil;
|
||||
|
||||
FeedDetailTableCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell.storyImageUrl) {
|
||||
id cachedImage = appDelegate.cachedStoryImages[cell.storyImageUrl];
|
||||
if (cell.storyHash) {
|
||||
id cachedImage = appDelegate.cachedStoryImages[cell.storyHash];
|
||||
if (cachedImage && cachedImage != [NSNull null])
|
||||
storyImage = cachedImage;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ typedef NS_ENUM(NSUInteger, FeedDetailTextSize)
|
|||
NSString *storyAuthor;
|
||||
NSString *storyDate;
|
||||
NSString *storyContent;
|
||||
NSString *storyImageUrl;
|
||||
NSString *storyHash;
|
||||
UIImage *storyImage;
|
||||
NSInteger storyTimestamp;
|
||||
int storyScore;
|
||||
|
@ -56,7 +56,7 @@ typedef NS_ENUM(NSUInteger, FeedDetailTextSize)
|
|||
@property (nonatomic) NSString *storyAuthor;
|
||||
@property (nonatomic) NSString *storyDate;
|
||||
@property (nonatomic) NSString *storyContent;
|
||||
@property (nonatomic) NSString *storyImageUrl;
|
||||
@property (nonatomic) NSString *storyHash;
|
||||
@property (nonatomic) UIImage *storyImage;
|
||||
@property (nonatomic) NSInteger storyTimestamp;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ static UIFont *indicatorFont = nil;
|
|||
@synthesize storyAuthor;
|
||||
@synthesize storyDate;
|
||||
@synthesize storyContent;
|
||||
@synthesize storyImageUrl;
|
||||
@synthesize storyHash;
|
||||
@synthesize storyTimestamp;
|
||||
@synthesize storyScore;
|
||||
@synthesize storyImage;
|
||||
|
@ -229,7 +229,7 @@ static UIFont *indicatorFont = nil;
|
|||
|
||||
CGContextFillRect(context, r);
|
||||
|
||||
if (cell.storyImageUrl) {
|
||||
if (cell.storyHash) {
|
||||
CGRect imageFrame = CGRectMake(r.size.width - imageWidth - previewHorizMargin, topMargin,
|
||||
imageWidth, imageHeight);
|
||||
|
||||
|
@ -245,7 +245,8 @@ static UIFont *indicatorFont = nil;
|
|||
}
|
||||
}
|
||||
|
||||
UIImage *cachedImage = (UIImage *)[appDelegate.cachedStoryImages objectForKey:cell.storyImageUrl];
|
||||
UIImage *cachedImage = (UIImage *)appDelegate.cachedStoryImages[cell.storyHash];
|
||||
|
||||
if (cachedImage && ![cachedImage isKindOfClass:[NSNull class]]) {
|
||||
// NSLog(@"Found cached image: %@", cell.storyTitle);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
|
Loading…
Add table
Reference in a new issue