mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
Reading cached images and using in stories. A single iamge is nowhere near enough. Need a refactor to account for all images.
This commit is contained in:
parent
7625251c22
commit
8bcfc5d565
7 changed files with 127 additions and 28 deletions
|
@ -425,7 +425,8 @@
|
|||
[self showLoadingNotifier];
|
||||
} else if (!self.isOffline) {
|
||||
[self showLoadingNotifier];
|
||||
}
|
||||
}
|
||||
[appDelegate prepareActiveCachedImages:db];
|
||||
}];
|
||||
|
||||
self.pageFinished = YES;
|
||||
|
@ -644,12 +645,11 @@
|
|||
[appDelegate.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
||||
for (NSDictionary *story in confirmedNewStories) {
|
||||
[db executeUpdate:@"INSERT into stories"
|
||||
"(story_feed_id, story_hash, story_timestamp, image_url, story_json) VALUES "
|
||||
"(?, ?, ?, ?, ?)",
|
||||
"(story_feed_id, story_hash, story_timestamp, story_json) VALUES "
|
||||
"(?, ?, ?, ?)",
|
||||
[story objectForKey:@"story_feed_id"],
|
||||
[story objectForKey:@"story_hash"],
|
||||
[story objectForKey:@"story_timestamp"],
|
||||
[story objectForKey:@"image_url"],
|
||||
[story JSONRepresentation]
|
||||
];
|
||||
}
|
||||
|
@ -862,7 +862,12 @@
|
|||
cell.storyScore = score;
|
||||
|
||||
if (self.isOffline) {
|
||||
BOOL read = ![[self.unreadStoryHashes objectForKey:[story objectForKey:@"story_hash"]] boolValue];
|
||||
BOOL read;
|
||||
if ([appDelegate.activeReadFilter isEqualToString:@"all"]) {
|
||||
read = ![[self.unreadStoryHashes objectForKey:[story objectForKey:@"story_hash"]] boolValue];
|
||||
} else {
|
||||
read = NO;
|
||||
}
|
||||
cell.isRead = read || ([[story objectForKey:@"read_status"] intValue] == 1);
|
||||
} else {
|
||||
cell.isRead = [[story objectForKey:@"read_status"] intValue] == 1;
|
||||
|
|
|
@ -141,6 +141,7 @@
|
|||
NSDictionary *categoryFeeds;
|
||||
UIImageView *splashView;
|
||||
ASINetworkQueue *operationQueue;
|
||||
NSMutableDictionary *activeCachedImages;
|
||||
}
|
||||
|
||||
@property (nonatomic) IBOutlet UIWindow *window;
|
||||
|
@ -236,6 +237,7 @@
|
|||
@property (nonatomic) NSDictionary *categoryFeeds;
|
||||
@property (readwrite) FMDatabaseQueue *database;
|
||||
@property (readwrite) ASINetworkQueue *operationQueue;
|
||||
@property (nonatomic) NSMutableDictionary *activeCachedImages;
|
||||
|
||||
+ (NewsBlurAppDelegate*) sharedAppDelegate;
|
||||
- (void)startupAnimationDone:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context;
|
||||
|
@ -334,7 +336,6 @@
|
|||
- (int)databaseSchemaVersion:(FMDatabase *)db;
|
||||
- (void)createDatabaseConnection;
|
||||
- (void)setupDatabase:(FMDatabase *)db;
|
||||
- (NSURL *)applicationDocumentsDirectory;
|
||||
- (void)fetchUnreadHashes;
|
||||
- (void)storeUnreadHashes:(ASIHTTPRequest *)request;
|
||||
- (void)fetchAllUnreadStories;
|
||||
|
@ -342,6 +343,8 @@
|
|||
- (void)flushQueuedReadStories:(BOOL)forceCheck withCallback:(void(^)())callback;
|
||||
- (void)syncQueuedReadStories:(FMDatabase *)db withStories:(NSDictionary *)hashes withCallback:(void(^)())callback;
|
||||
- (void)cachedImageQueueFinished:(ASINetworkQueue *)queue;
|
||||
- (void)flushOldCachedImages;
|
||||
- (void)prepareActiveCachedImages:(FMDatabase *)db;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
@implementation NewsBlurAppDelegate
|
||||
|
||||
#define CURRENT_DB_VERSION 17
|
||||
#define CURRENT_DB_VERSION 18
|
||||
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
|
||||
|
||||
@synthesize window;
|
||||
|
@ -146,6 +146,7 @@
|
|||
@synthesize categories;
|
||||
@synthesize categoryFeeds;
|
||||
@synthesize operationQueue;
|
||||
@synthesize activeCachedImages;
|
||||
|
||||
+ (NewsBlurAppDelegate*) sharedAppDelegate {
|
||||
return (NewsBlurAppDelegate*) [UIApplication sharedApplication].delegate;
|
||||
|
@ -2139,8 +2140,6 @@
|
|||
" story_feed_id number,"
|
||||
" story_hash varchar(24),"
|
||||
" story_timestamp number,"
|
||||
" image_url varchar(1024),"
|
||||
" image_cached boolean,"
|
||||
" story_json text,"
|
||||
" UNIQUE(story_hash) ON CONFLICT REPLACE"
|
||||
")"];
|
||||
|
@ -2173,19 +2172,30 @@
|
|||
")"];
|
||||
[db executeUpdate:createImagesTable];
|
||||
|
||||
NSLog(@"Create db %d: %@", [db lastErrorCode], [db lastErrorMessage]);
|
||||
}
|
||||
NSError *error;
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *storyImagesDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
||||
NSString *faviconsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"favicons"];
|
||||
NSString *avatarsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"avatars"];
|
||||
|
||||
// Returns the URL to the application's Documents directory.
|
||||
- (NSURL *)applicationDocumentsDirectory
|
||||
{
|
||||
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:storyImagesDirectory]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:storyImagesDirectory withIntermediateDirectories:NO attributes:nil error:&error];
|
||||
}
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:faviconsDirectory]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:faviconsDirectory withIntermediateDirectories:NO attributes:nil error:&error];
|
||||
}
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:avatarsDirectory]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:avatarsDirectory withIntermediateDirectories:NO attributes:nil error:&error];
|
||||
}
|
||||
|
||||
NSLog(@"Create db %d: %@", [db lastErrorCode], [db lastErrorMessage]);
|
||||
}
|
||||
|
||||
- (void)flushQueuedReadStories:(BOOL)forceCheck withCallback:(void(^)())callback {
|
||||
if (hasQueuedReadStories || forceCheck) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
|
||||
(unsigned long)NULL), ^(void) {
|
||||
[self flushOldCachedImages];
|
||||
[self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
||||
NSMutableDictionary *hashes = [NSMutableDictionary dictionary];
|
||||
FMResultSet *stories = [db executeQuery:@"SELECT * FROM queued_read_hashes"];
|
||||
|
@ -2387,12 +2397,11 @@
|
|||
[_self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
||||
for (NSDictionary *story in [results objectForKey:@"stories"]) {
|
||||
BOOL inserted = [db executeUpdate:@"INSERT into stories "
|
||||
"(story_feed_id, story_hash, story_timestamp, image_url, story_json) VALUES "
|
||||
"(?, ?, ?, ?, ?)",
|
||||
"(story_feed_id, story_hash, story_timestamp, story_json) VALUES "
|
||||
"(?, ?, ?, ?)",
|
||||
[story objectForKey:@"story_feed_id"],
|
||||
[story objectForKey:@"story_hash"],
|
||||
[story objectForKey:@"story_timestamp"],
|
||||
[story objectForKey:@"image_url"],
|
||||
[story JSONRepresentation]
|
||||
];
|
||||
if ([[story objectForKey:@"image_url"] class] != [NSNull class]) {
|
||||
|
@ -2519,7 +2528,7 @@
|
|||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *cacheDirectory = [paths objectAtIndex:0];
|
||||
NSString *cacheDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
||||
NSString *fullPath = [cacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", md5Url]];
|
||||
|
||||
[fileManager createFileAtPath:fullPath contents:responseData attributes:nil];
|
||||
|
@ -2542,6 +2551,54 @@
|
|||
// });
|
||||
}
|
||||
|
||||
- (void)flushOldCachedImages {
|
||||
int deleted = 0;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *cacheDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
||||
NSDirectoryEnumerator* en = [fileManager enumeratorAtPath:cacheDirectory];
|
||||
|
||||
NSString* file;
|
||||
while (file = [en nextObject])
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSString *filepath = [NSString stringWithFormat:[cacheDirectory stringByAppendingString:@"/%@"],file];
|
||||
NSDate *creationDate = [[fileManager attributesOfItemAtPath:filepath error:nil] fileCreationDate];
|
||||
NSDate *d = [[NSDate date] dateByAddingTimeInterval:-14*24*60*60];
|
||||
NSDateFormatter *df = [NSDateFormatter alloc]; // = [NSDateFormatter initWithDateFormat:@"yyyy-MM-dd"];
|
||||
[df setDateFormat:@"EEEE d"];
|
||||
|
||||
if ([creationDate compare:d] == NSOrderedAscending) {
|
||||
[[NSFileManager defaultManager]
|
||||
removeItemAtPath:[cacheDirectory stringByAppendingPathComponent:file]
|
||||
error:&error];
|
||||
deleted += 1;
|
||||
}
|
||||
}
|
||||
NSLog(@"Deleted %d old cached images", deleted);
|
||||
}
|
||||
|
||||
- (void)prepareActiveCachedImages:(FMDatabase *)db {
|
||||
activeCachedImages = [NSMutableDictionary dictionary];
|
||||
|
||||
NSArray *feedIds;
|
||||
|
||||
if (isRiverView) {
|
||||
feedIds = activeFolderFeeds;
|
||||
} else if (activeFeed) {
|
||||
feedIds = @[[activeFeed objectForKey:@"id"]];
|
||||
}
|
||||
NSString *sql = [NSString stringWithFormat:@"SELECT c.image_url, c.story_hash FROM cached_images c "
|
||||
"INNER JOIN unread_hashes u ON (c.story_hash = u.story_hash) "
|
||||
"WHERE c.image_cached = 1 AND c.story_feed_id in (%@)",
|
||||
[feedIds componentsJoinedByString:@","]];
|
||||
FMResultSet *cursor = [db executeQuery:sql];
|
||||
|
||||
while ([cursor next]) {
|
||||
[activeCachedImages setObject:[cursor objectForColumnName:@"image_url"] forKey:[cursor objectForColumnName:@"story_hash"]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
|
|
@ -117,6 +117,7 @@ IASKSettingsDelegate> {
|
|||
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender;
|
||||
- (void)settingDidChange:(NSNotification*)notification;
|
||||
|
||||
- (void)showRefreshNotifier;
|
||||
- (void)showSyncingNotifier;
|
||||
- (void)showSyncingNotifier:(float)progress hoursBack:(int)days;
|
||||
- (void)showCachingNotifier:(float)progress hoursBack:(int)hours;
|
||||
|
|
|
@ -497,8 +497,8 @@ static const CGFloat kFolderTitleHeight = 28;
|
|||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
|
||||
(unsigned long)NULL), ^(void) {
|
||||
[appDelegate.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
||||
[db executeUpdate:@"DELETE FROM feeds WHERE username = ?", appDelegate.activeUsername];
|
||||
[db executeUpdate:@"INSERT into feeds"
|
||||
[db executeUpdate:@"DELETE FROM accounts WHERE username = ?", appDelegate.activeUsername];
|
||||
[db executeUpdate:@"INSERT INTO accounts"
|
||||
"(username, download_date, feeds_json) VALUES "
|
||||
"(?, ?, ?)",
|
||||
appDelegate.activeUsername,
|
||||
|
@ -767,7 +767,7 @@ static const CGFloat kFolderTitleHeight = 28;
|
|||
if (!appDelegate.activeUsername) return;
|
||||
}
|
||||
|
||||
FMResultSet *cursor = [db executeQuery:@"SELECT * FROM feeds WHERE username = ? LIMIT 1",
|
||||
FMResultSet *cursor = [db executeQuery:@"SELECT * FROM accounts WHERE username = ? LIMIT 1",
|
||||
appDelegate.activeUsername];
|
||||
|
||||
while ([cursor next]) {
|
||||
|
@ -1104,6 +1104,8 @@ static const CGFloat kFolderTitleHeight = 28;
|
|||
|
||||
- (CGFloat)tableView:(UITableView *)tableView
|
||||
heightForHeaderInSection:(NSInteger)section {
|
||||
if ([appDelegate.dictFoldersArray count] == 0) return 0;
|
||||
|
||||
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:section];
|
||||
|
||||
BOOL visibleFeeds = [[self.visibleFolders objectForKey:folderName] boolValue];
|
||||
|
@ -1493,6 +1495,10 @@ heightForHeaderInSection:(NSInteger)section {
|
|||
[request setDidFailSelector:@selector(requestFailed:)];
|
||||
[request setTimeOutSeconds:30];
|
||||
[request startAsynchronous];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self showRefreshNotifier];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)finishRefreshingFeedList:(ASIHTTPRequest *)request {
|
||||
|
@ -1703,8 +1709,15 @@ heightForHeaderInSection:(NSInteger)section {
|
|||
self.navigationItem.titleView = userInfoView;
|
||||
}
|
||||
|
||||
- (void)showSyncingNotifier {
|
||||
- (void)showRefreshNotifier {
|
||||
[self.notifier hide];
|
||||
self.notifier.style = NBSyncingStyle;
|
||||
self.notifier.title = @"Counting is difficult...";
|
||||
[self.notifier setProgress:0];
|
||||
[self.notifier show];
|
||||
}
|
||||
|
||||
- (void)showSyncingNotifier {
|
||||
self.notifier.style = NBSyncingStyle;
|
||||
self.notifier.title = @"Syncing stories...";
|
||||
[self.notifier setProgress:0];
|
||||
|
@ -1715,13 +1728,13 @@ heightForHeaderInSection:(NSInteger)section {
|
|||
// [self.notifier hide];
|
||||
self.notifier.style = NBSyncingProgressStyle;
|
||||
if (hours < 2) {
|
||||
self.notifier.title = @"Storing last hour";
|
||||
self.notifier.title = @"Storing past hour";
|
||||
} else if (hours < 24) {
|
||||
self.notifier.title = [NSString stringWithFormat:@"Storing %d hours", hours];
|
||||
self.notifier.title = [NSString stringWithFormat:@"Storing past %d hours", hours];
|
||||
} else if (hours < 48) {
|
||||
self.notifier.title = @"Storing yesterday";
|
||||
} else {
|
||||
self.notifier.title = [NSString stringWithFormat:@"Storing %d days ago", (int)round(hours / 24.f)];
|
||||
self.notifier.title = [NSString stringWithFormat:@"Storing past %d days", (int)round(hours / 24.f)];
|
||||
}
|
||||
[self.notifier setProgress:progress];
|
||||
[self.notifier setNeedsDisplay];
|
||||
|
@ -1734,7 +1747,7 @@ heightForHeaderInSection:(NSInteger)section {
|
|||
if (hours < 2) {
|
||||
self.notifier.title = @"Images from last hour";
|
||||
} else if (hours < 24) {
|
||||
self.notifier.title = [NSString stringWithFormat:@"Images from %d hours", hours];
|
||||
self.notifier.title = [NSString stringWithFormat:@"Images from %d hours ago", hours];
|
||||
} else if (hours < 48) {
|
||||
self.notifier.title = @"Images from yesterday";
|
||||
} else {
|
||||
|
|
|
@ -127,6 +127,7 @@
|
|||
NSString *footerString;
|
||||
NSString *fontStyleClass = @"";
|
||||
NSString *fontSizeClass = @"";
|
||||
NSString *storyContent = [self.activeStory objectForKey:@"story_content"];
|
||||
|
||||
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
if ([userPreferences stringForKey:@"fontStyle"]){
|
||||
|
@ -151,6 +152,15 @@
|
|||
contentWidthClass = @"NB-iphone";
|
||||
}
|
||||
|
||||
if (appDelegate.feedDetailViewController.isOffline) {
|
||||
NSString *storyHash = [self.activeStory objectForKey:@"story_hash"];
|
||||
NSString *imageUrl = [appDelegate.activeCachedImages objectForKey:storyHash];
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *storyImagesDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
||||
NSString *cachedImage = [storyImagesDirectory stringByAppendingPathComponent:[Utilities md5:imageUrl]];
|
||||
storyContent = [[self.activeStory objectForKey:@"story_content"] stringByReplacingOccurrencesOfString:imageUrl withString:cachedImage];
|
||||
}
|
||||
|
||||
NSString *riverClass = (appDelegate.isRiverView || appDelegate.isSocialView) ?
|
||||
@"NB-river" : @"NB-non-river";
|
||||
|
||||
|
@ -207,7 +217,7 @@
|
|||
fontSizeClass,
|
||||
storyHeader,
|
||||
shareBarString,
|
||||
[self.activeStory objectForKey:@"story_content"],
|
||||
storyContent,
|
||||
sharingHtmlString,
|
||||
commentString,
|
||||
footerString
|
||||
|
|
|
@ -64,6 +64,11 @@ static NSMutableDictionary *imageCache;
|
|||
// Image not in cache, search on disk.
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *cacheDirectory = [paths objectAtIndex:0];
|
||||
if (isSocial) {
|
||||
cacheDirectory = [cacheDirectory stringByAppendingPathComponent:@"avatars"];
|
||||
} else {
|
||||
cacheDirectory = [cacheDirectory stringByAppendingPathComponent:@"favicons"];
|
||||
}
|
||||
NSString *path = [cacheDirectory stringByAppendingPathComponent:filename];
|
||||
|
||||
image = [UIImage imageWithContentsOfFile:path];
|
||||
|
@ -112,6 +117,11 @@ static NSMutableDictionary *imageCache;
|
|||
for (NSString *filename in [imageCache allKeys]) {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *cacheDirectory = [paths objectAtIndex:0];
|
||||
if ([filename hasPrefix:@"social"]) {
|
||||
cacheDirectory = [cacheDirectory stringByAppendingPathComponent:@"avatars"];
|
||||
} else {
|
||||
cacheDirectory = [cacheDirectory stringByAppendingPathComponent:@"favicons"];
|
||||
}
|
||||
NSString *path = [cacheDirectory stringByAppendingPathComponent:filename];
|
||||
|
||||
// Save image to disk
|
||||
|
|
Loading…
Add table
Reference in a new issue