mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-21 05:45:13 +00:00
Adding NSURLCache layer for caching of offline images. No more rewriting of image URLs. Thanks to @zacwest for the push on this.
This commit is contained in:
parent
de7a84e5a2
commit
aaf6ea042e
7 changed files with 132 additions and 24 deletions
|
@ -55,11 +55,12 @@
|
|||
#import "NSString+HTML.h"
|
||||
#import "UIView+ViewController.h"
|
||||
#import "UIViewController+OSKUtilities.h"
|
||||
#import "NBURLCache.h"
|
||||
#import <float.h>
|
||||
|
||||
@implementation NewsBlurAppDelegate
|
||||
|
||||
#define CURRENT_DB_VERSION 31
|
||||
#define CURRENT_DB_VERSION 32
|
||||
|
||||
@synthesize window;
|
||||
|
||||
|
@ -209,7 +210,11 @@
|
|||
|
||||
cachedFavicons = [[TMCache alloc] initWithName:@"NBFavicons"];
|
||||
cachedStoryImages = [[TMCache alloc] initWithName:@"NBStoryImages"];
|
||||
|
||||
|
||||
NBURLCache *urlCache = [[NBURLCache alloc] init];
|
||||
[NSURLCache setSharedURLCache:urlCache];
|
||||
[[NSURLCache sharedURLCache] removeAllCachedResponses];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
|
|
@ -279,6 +279,8 @@
|
|||
{
|
||||
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
|
||||
|
||||
// if (error.code == 102 && [error.domain isEqual:@"WebKitErrorDomain"]) { }
|
||||
|
||||
// User clicking on another link before the page loads is OK.
|
||||
if ([error code] != NSURLErrorCancelled) {
|
||||
[self informError:error];
|
||||
|
@ -293,18 +295,25 @@
|
|||
}
|
||||
|
||||
- (IBAction)loadAddress:(id)sender {
|
||||
if (!activeUrl) {
|
||||
activeUrl = [appDelegate.activeOriginalStoryURL absoluteString];
|
||||
}
|
||||
activeUrl = [appDelegate.activeOriginalStoryURL absoluteString];
|
||||
NSString* urlString = activeUrl;
|
||||
NSURL* url = [NSURL URLWithString:urlString];
|
||||
// if ([urlString containsString:@"story_images"]) {
|
||||
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
// NSString *storyImagesDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
||||
//
|
||||
// urlString = [urlString substringFromIndex:NSMaxRange([urlString
|
||||
// rangeOfString:@"story_images/"])];
|
||||
// NSString *path = [storyImagesDirectory stringByAppendingPathComponent:urlString];
|
||||
// url = [NSURL fileURLWithPath:path];
|
||||
// }
|
||||
if (!url.scheme) {
|
||||
NSString* modifiedURLString = [NSString stringWithFormat:@"%@", urlString];
|
||||
url = [NSURL URLWithString:modifiedURLString];
|
||||
}
|
||||
if ([self.webView isLoading]) {
|
||||
[self.webView stopLoading];
|
||||
}
|
||||
// if ([self.webView isLoading]) {
|
||||
// [self.webView stopLoading];
|
||||
// }
|
||||
NSURLRequest* request = [NSURLRequest requestWithURL:url];
|
||||
[self.webView loadRequest:request];
|
||||
titleView.text = @"Loading...";
|
||||
|
|
|
@ -272,20 +272,20 @@
|
|||
contentWidthClass, (int)floorf(CGRectGetWidth(self.view.frame))];
|
||||
|
||||
// Replace image urls that are locally cached, even when online
|
||||
NSString *storyHash = [self.activeStory objectForKey:@"story_hash"];
|
||||
NSArray *imageUrls = [appDelegate.activeCachedImages objectForKey:storyHash];
|
||||
if (imageUrls) {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *storyImagesDirectory = [[paths objectAtIndex:0]
|
||||
stringByAppendingPathComponent:@"story_images"];
|
||||
for (NSString *imageUrl in imageUrls) {
|
||||
NSString *cachedImage = [storyImagesDirectory
|
||||
stringByAppendingPathComponent:[Utilities md5:imageUrl]];
|
||||
storyContent = [storyContent
|
||||
stringByReplacingOccurrencesOfString:imageUrl
|
||||
withString:cachedImage];
|
||||
}
|
||||
}
|
||||
// NSString *storyHash = [self.activeStory objectForKey:@"story_hash"];
|
||||
// NSArray *imageUrls = [appDelegate.activeCachedImages objectForKey:storyHash];
|
||||
// if (imageUrls) {
|
||||
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
// NSString *storyImagesDirectory = [[paths objectAtIndex:0]
|
||||
// stringByAppendingPathComponent:@"story_images"];
|
||||
// for (NSString *imageUrl in imageUrls) {
|
||||
// NSString *cachedImage = [storyImagesDirectory
|
||||
// stringByAppendingPathComponent:[Utilities md5:imageUrl]];
|
||||
// storyContent = [storyContent
|
||||
// stringByReplacingOccurrencesOfString:imageUrl
|
||||
// withString:cachedImage];
|
||||
// }
|
||||
// }
|
||||
|
||||
NSString *riverClass = (appDelegate.storiesCollection.isRiverView ||
|
||||
appDelegate.storiesCollection.isSocialView ||
|
||||
|
@ -1552,7 +1552,8 @@ shouldStartLoadWithRequest:(NSURLRequest *)request
|
|||
actionSheetViewImageIndex = [actions addButtonWithTitle:@"View and zoom"];
|
||||
actionSheetCopyImageIndex = [actions addButtonWithTitle:@"Copy image"];
|
||||
actionSheetSaveImageIndex = [actions addButtonWithTitle:@"Save to camera roll"];
|
||||
[actions showFromRect:CGRectMake(pt.x, pt.y, 1, 1) inView:appDelegate.storyPageControl.view animated:YES];
|
||||
[actions showFromRect:CGRectMake(pt.x, pt.y, 1, 1)
|
||||
inView:appDelegate.storyPageControl.view animated:YES];
|
||||
// [actions showInView:appDelegate.storyPageControl.view];
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@
|
|||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *cacheDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
||||
NSString *fullPath = [cacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", md5Url]];
|
||||
NSString *fullPath = [cacheDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", md5Url, [[[request originalURL] absoluteString] pathExtension]]];
|
||||
|
||||
[fileManager createFileAtPath:fullPath contents:responseData attributes:nil];
|
||||
} else {
|
||||
|
|
|
@ -675,6 +675,7 @@
|
|||
FFF1E4CB17750D2C00BF59D3 /* menu_icn_preferences.png in Resources */ = {isa = PBXBuildFile; fileRef = FFF1E4C917750D2C00BF59D3 /* menu_icn_preferences.png */; };
|
||||
FFF1E4CC17750D2C00BF59D3 /* menu_icn_preferences@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFF1E4CA17750D2C00BF59D3 /* menu_icn_preferences@2x.png */; };
|
||||
FFFC608517165A1D00DC22E2 /* THCircularProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = FFFC60831716578E00DC22E2 /* THCircularProgressView.m */; };
|
||||
FFFF683D19D628000081904A /* NBURLCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FFFF683C19D628000081904A /* NBURLCache.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -1623,6 +1624,8 @@
|
|||
FFF1E4CA17750D2C00BF59D3 /* menu_icn_preferences@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menu_icn_preferences@2x.png"; sourceTree = "<group>"; };
|
||||
FFFC60821716578E00DC22E2 /* THCircularProgressView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = THCircularProgressView.h; sourceTree = "<group>"; };
|
||||
FFFC60831716578E00DC22E2 /* THCircularProgressView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = THCircularProgressView.m; sourceTree = "<group>"; };
|
||||
FFFF683B19D628000081904A /* NBURLCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NBURLCache.h; path = "Other Sources/NBURLCache.h"; sourceTree = "<group>"; };
|
||||
FFFF683C19D628000081904A /* NBURLCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NBURLCache.m; path = "Other Sources/NBURLCache.m"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -1742,6 +1745,8 @@
|
|||
FF1F13D718AAC97900FDA816 /* UIImage+Resize.m */,
|
||||
FFA0483F19CA5F5B00618DC4 /* UIWebView+Offsets.h */,
|
||||
FFA0484019CA5F5B00618DC4 /* UIWebView+Offsets.m */,
|
||||
FFFF683B19D628000081904A /* NBURLCache.h */,
|
||||
FFFF683C19D628000081904A /* NBURLCache.m */,
|
||||
);
|
||||
name = "Other Sources";
|
||||
sourceTree = "<group>";
|
||||
|
@ -3498,6 +3503,7 @@
|
|||
1D3623260D0F684500981E51 /* NewsBlurAppDelegate.m in Sources */,
|
||||
FFA047DA19CA54A800618DC4 /* NSMutableURLRequest+OSKUtilities.m in Sources */,
|
||||
28D7ACF80DDB3853001CB0EB /* NewsBlurViewController.m in Sources */,
|
||||
FFFF683D19D628000081904A /* NBURLCache.m in Sources */,
|
||||
FFA0481619CA54A800618DC4 /* OSKPagedHorizontalLayout.m in Sources */,
|
||||
78FC34F711CA94900055C312 /* NSObject+SBJSON.m in Sources */,
|
||||
FFA0482119CA54A800618DC4 /* OSKSaveToCameraRollActivity.m in Sources */,
|
||||
|
|
15
clients/ios/Other Sources/NBURLCache.h
Normal file
15
clients/ios/Other Sources/NBURLCache.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// NBURLCache.h
|
||||
// NewsBlur
|
||||
//
|
||||
// Created by Samuel Clay on 9/26/14.
|
||||
// Copyright (c) 2014 NewsBlur. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NBURLCache : NSURLCache {
|
||||
NSMutableDictionary *cachedResponses;
|
||||
}
|
||||
|
||||
@end
|
72
clients/ios/Other Sources/NBURLCache.m
Normal file
72
clients/ios/Other Sources/NBURLCache.m
Normal file
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// NBURLCache.m
|
||||
// NewsBlur
|
||||
//
|
||||
// Created by Samuel Clay on 9/26/14.
|
||||
// Copyright (c) 2014 NewsBlur. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NBURLCache.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
@implementation NBURLCache
|
||||
|
||||
- (NSString *)substitutePath:(NSString *)pathString {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *storyImagesDirectory = [[paths objectAtIndex:0]
|
||||
stringByAppendingPathComponent:@"story_images"];
|
||||
NSString *cachedImage = [[storyImagesDirectory
|
||||
stringByAppendingPathComponent:[Utilities md5:pathString]] stringByAppendingPathExtension:[pathString pathExtension]];
|
||||
return cachedImage;
|
||||
}
|
||||
|
||||
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
|
||||
{
|
||||
// Get the path for the request
|
||||
NSString *pathString = [[request URL] absoluteString];
|
||||
|
||||
// See if we have a substitution file for this path
|
||||
NSString *substitutionFileName = [self substitutePath:pathString];
|
||||
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:substitutionFileName];
|
||||
if (!substitutionFileName || !exists)
|
||||
{
|
||||
NSLog(@"No cache found: %@ / %@", pathString, substitutionFileName);
|
||||
// No substitution file, return the default cache response
|
||||
return [super cachedResponseForRequest:request];
|
||||
}
|
||||
|
||||
// If we've already created a cache entry for this path, then return it.
|
||||
NSCachedURLResponse *cachedResponse = [cachedResponses objectForKey:pathString];
|
||||
if (cachedResponse)
|
||||
{
|
||||
NSLog(@"Memory cached: %@", pathString);
|
||||
// return cachedResponse;
|
||||
}
|
||||
|
||||
// Get the path to the substitution file
|
||||
NSString *substitutionFilePath = substitutionFileName;
|
||||
|
||||
// Load the data
|
||||
NSData *data = [NSData dataWithContentsOfFile:substitutionFilePath];
|
||||
|
||||
// Create the cacheable response
|
||||
NSURLResponse *response = [[NSURLResponse alloc]
|
||||
initWithURL:[request URL]
|
||||
MIMEType:nil
|
||||
expectedContentLength:[data length]
|
||||
textEncodingName:nil];
|
||||
cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response
|
||||
data:data];
|
||||
|
||||
NSLog(@"Got cached response: %@ / %@", pathString, substitutionFileName);
|
||||
// Add it to our cache dictionary for subsequent responses
|
||||
if (!cachedResponses)
|
||||
{
|
||||
cachedResponses = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
[cachedResponses setObject:cachedResponse forKey:pathString];
|
||||
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Add table
Reference in a new issue