├── .gitignore ├── README.md ├── e-Hentai.xcodeproj ├── project.pbxproj ├── project.pbxproj.orig ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── ChilunChen.xcuserdatad │ └── xcschemes │ └── e-Hantai.xcscheme ├── e-Hentai ├── AppDelegate.h ├── AppDelegate.m ├── Common │ ├── FakeViewController.h │ ├── FakeViewController.m │ ├── HentaiNavigationController.h │ └── HentaiNavigationController.m ├── DownloadedViewController │ ├── DownloadedViewController.h │ └── DownloadedViewController.m ├── HentaiDownloadCenter │ ├── HentaiDownloadBookOperation.h │ ├── HentaiDownloadBookOperation.m │ ├── HentaiDownloadCenter.h │ ├── HentaiDownloadCenter.m │ ├── HentaiDownloadImageOperation.h │ └── HentaiDownloadImageOperation.m ├── HentaiParser │ ├── HentaiParser.h │ └── HentaiParser.m ├── HentaiSearchFilter │ ├── HentaiFilterView.h │ ├── HentaiFilterView.m │ ├── HentaiSearchFilter.h │ └── HentaiSearchFilter.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── MainViewController │ ├── GalleryCell │ │ ├── CategoryTitle.h │ │ ├── CategoryTitle.m │ │ ├── GalleryCell.h │ │ ├── GalleryCell.m │ │ ├── GalleryCell.xib │ │ ├── RatingStar.h │ │ └── RatingStar.m │ ├── MainViewController.h │ ├── MainViewController.m │ └── MainViewController.xib ├── PhotoViewController │ ├── HentaiPhotoCell.h │ ├── HentaiPhotoCell.m │ ├── HentaiPhotoCell.xib │ ├── PhotoViewController.h │ ├── PhotoViewController.m │ └── PhotoViewController.xib ├── ThirdParty │ ├── FilesManager │ │ ├── FMStream.h │ │ ├── FMStream.m │ │ ├── FilesManager.h │ │ └── FilesManager.m │ ├── Hpple │ │ ├── TFHpple.h │ │ ├── TFHpple.m │ │ ├── TFHppleElement.h │ │ ├── TFHppleElement.m │ │ ├── XPathQuery.h │ │ └── XPathQuery.m │ ├── LightWeightPlist │ │ ├── LightWeightPlist+AccessObject.h │ │ ├── LightWeightPlist+AccessObject.m │ │ ├── LightWeightPlist+FilePath.h │ │ ├── LightWeightPlist+FilePath.m │ │ ├── LightWeightPlist+HandleCache.h │ │ ├── LightWeightPlist+HandleCache.m │ │ ├── LightWeightPlist+SourceFromDisk.h │ │ ├── LightWeightPlist+SourceFromDisk.m │ │ ├── LightWeightPlist.h │ │ ├── LightWeightPlist.m │ │ ├── LightWeightPlistObjects.h │ │ └── LightWeightPlistObjects.m │ ├── SDWebImage │ │ ├── MKAnnotationView+WebCache.h │ │ ├── MKAnnotationView+WebCache.m │ │ ├── NSData+ImageContentType.h │ │ ├── NSData+ImageContentType.m │ │ ├── SDImageCache.h │ │ ├── SDImageCache.m │ │ ├── SDWebImageCompat.h │ │ ├── SDWebImageCompat.m │ │ ├── SDWebImageDecoder.h │ │ ├── SDWebImageDecoder.m │ │ ├── SDWebImageDownloader.h │ │ ├── SDWebImageDownloader.m │ │ ├── SDWebImageDownloaderOperation.h │ │ ├── SDWebImageDownloaderOperation.m │ │ ├── SDWebImageManager.h │ │ ├── SDWebImageManager.m │ │ ├── SDWebImageOperation.h │ │ ├── SDWebImagePrefetcher.h │ │ ├── SDWebImagePrefetcher.m │ │ ├── UIButton+WebCache.h │ │ ├── UIButton+WebCache.m │ │ ├── UIImage+GIF.h │ │ ├── UIImage+GIF.m │ │ ├── UIImage+MultiFormat.h │ │ ├── UIImage+MultiFormat.m │ │ ├── UIImage+WebP.h │ │ ├── UIImage+WebP.m │ │ ├── UIImageView+HighlightedWebCache.h │ │ ├── UIImageView+HighlightedWebCache.m │ │ ├── UIImageView+WebCache.h │ │ ├── UIImageView+WebCache.m │ │ ├── UIView+WebCacheOperation.h │ │ └── UIView+WebCacheOperation.m │ └── SVProgressHUD │ │ ├── SVProgressHUD-Prefix.pch │ │ ├── SVProgressHUD.bundle │ │ ├── angle-mask@2x.png │ │ ├── error@2x.png │ │ └── success@2x.png │ │ ├── SVProgressHUD.h │ │ └── SVProgressHUD.m ├── e-Hentai-Info.plist ├── e-Hentai-Prefix.pch ├── en.lproj │ └── InfoPlist.strings └── main.m └── e-HentaiTests ├── e-HentaiTests-Info.plist ├── e_HentaiTests.m └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://www.gitignore.io 2 | 3 | #!! ERROR: xc is undefined. Use list command to see defined gitignore types !!# 4 | 5 | ### Xcode ### 6 | build/ 7 | *.pbxuser 8 | !default.pbxuser 9 | *.mode1v3 10 | !default.mode1v3 11 | *.mode2v3 12 | !default.mode2v3 13 | *.perspectivev3 14 | !default.perspectivev3 15 | xcuserdata 16 | *.xccheckout 17 | *.moved-aside 18 | DerivedData 19 | *.xcuserstate 20 | 21 | 22 | ### Objective-C ### 23 | # Xcode 24 | # 25 | build/ 26 | *.pbxuser 27 | !default.pbxuser 28 | *.mode1v3 29 | !default.mode1v3 30 | *.mode2v3 31 | !default.mode2v3 32 | *.perspectivev3 33 | !default.perspectivev3 34 | xcuserdata 35 | *.xccheckout 36 | *.moved-aside 37 | DerivedData 38 | *.hmap 39 | *.ipa 40 | *.xcuserstate 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 47 | # 48 | # Pods/ 49 | 50 | 51 | ### OSX ### 52 | .DS_Store 53 | .AppleDouble 54 | .LSOverride 55 | 56 | # Icon must end with two \r 57 | Icon 58 | 59 | 60 | # Thumbnails 61 | ._* 62 | 63 | # Files that might appear on external disk 64 | .Spotlight-V100 65 | .Trashes 66 | 67 | # Directories potentially created on remote AFP share 68 | .AppleDB 69 | .AppleDesktop 70 | Network Trash Folder 71 | Temporary Items 72 | .apdisk 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | e-Hentai 2 | ======== 3 | 4 | iOS e-Hentai Reader 5 | -------------------------------------------------------------------------------- /e-Hentai.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /e-Hentai.xcodeproj/xcuserdata/ChilunChen.xcuserdatad/xcschemes/e-Hantai.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /e-Hentai/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/8/27. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "HentaiNavigationController.h" 12 | #import "MainViewController.h" 13 | 14 | @interface AppDelegate : UIResponder 15 | 16 | @property (strong, nonatomic) UIWindow *window; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /e-Hentai/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/8/27. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 14 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 15 | HentaiNavigationController *hentaiNavigation = [[HentaiNavigationController alloc] initWithRootViewController:[MainViewController new]]; 16 | hentaiNavigation.autorotate = NO; 17 | hentaiNavigation.hentaiMask = UIInterfaceOrientationMaskPortrait; 18 | self.window.rootViewController = hentaiNavigation; 19 | [self.window makeKeyAndVisible]; 20 | return YES; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /e-Hentai/Common/FakeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FakeViewController.h 3 | // TEST_2014_9_2 4 | // 5 | // Created by 啟倫 陳 on 2014/9/3. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FakeViewController : UIViewController 12 | 13 | @property (nonatomic, copy) void (^BackBlock)(void); 14 | 15 | - (void)onPresentCompletion; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /e-Hentai/Common/FakeViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FakeViewController.m 3 | // TEST_2014_9_2 4 | // 5 | // Created by 啟倫 陳 on 2014/9/3. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "FakeViewController.h" 10 | 11 | @interface FakeViewController () 12 | 13 | @end 14 | 15 | @implementation FakeViewController 16 | 17 | - (void)onPresentCompletion 18 | { 19 | [self dismissViewControllerAnimated:NO completion: ^{ 20 | self.BackBlock(); 21 | }]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /e-Hentai/Common/HentaiNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiNavigationController.h 3 | // TEST_2014_9_2 4 | // 5 | // Created by 啟倫 陳 on 2014/9/3. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HentaiNavigationController : UINavigationController 12 | 13 | @property (nonatomic, assign) BOOL autorotate; 14 | @property (nonatomic, assign) UIInterfaceOrientationMask hentaiMask; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /e-Hentai/Common/HentaiNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiNavigationController.m 3 | // TEST_2014_9_2 4 | // 5 | // Created by 啟倫 陳 on 2014/9/3. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "HentaiNavigationController.h" 10 | 11 | @interface HentaiNavigationController () 12 | 13 | @end 14 | 15 | @implementation HentaiNavigationController 16 | 17 | 18 | #pragma mark - Configuring the View Rotation Settings 19 | 20 | - (BOOL)shouldAutorotate { 21 | return self.autorotate; 22 | } 23 | 24 | - (NSUInteger)supportedInterfaceOrientations { 25 | return self.hentaiMask; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /e-Hentai/DownloadedViewController/DownloadedViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadedViewController.h 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/29. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "MainViewController.h" 10 | 11 | @interface DownloadedViewController : MainViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /e-Hentai/DownloadedViewController/DownloadedViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadedViewController.m 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/29. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "DownloadedViewController.h" 10 | 11 | @interface DownloadedViewController () 12 | 13 | @property (nonatomic, strong) NSMutableArray *listArray; 14 | 15 | @end 16 | 17 | @implementation DownloadedViewController 18 | 19 | #pragma mark - UICollectionViewDataSource 20 | 21 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 22 | return [HentaiSaveLibraryArray count]; 23 | } 24 | 25 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 26 | GalleryCell *cell = (GalleryCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"GalleryCell" forIndexPath:indexPath]; 27 | NSDictionary *hentaiInfo = HentaiSaveLibraryArray[indexPath.row][@"hentaiInfo"]; 28 | [hentaiInfo setValue:@(YES) forKey:imageMode]; 29 | [cell setGalleryDict:hentaiInfo]; 30 | return cell; 31 | } 32 | 33 | #pragma mark - UICollectionViewDelegate 34 | 35 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 36 | NSDictionary *hentaiInfo = HentaiSaveLibraryArray[indexPath.row][@"hentaiInfo"]; 37 | HentaiNavigationController *hentaiNavigation = (HentaiNavigationController *)self.navigationController; 38 | hentaiNavigation.autorotate = YES; 39 | hentaiNavigation.hentaiMask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape; 40 | PhotoViewController *photoViewController = [PhotoViewController new]; 41 | photoViewController.hentaiInfo = hentaiInfo; 42 | [hentaiNavigation pushViewController:photoViewController animated:YES]; 43 | } 44 | 45 | #pragma mark - recv notification 46 | 47 | - (void)hentaiDownloadSuccess:(NSNotification *)notification { 48 | [self.listCollectionView reloadData]; 49 | } 50 | 51 | #pragma mark - ibaction 52 | 53 | //override 這個 method 避免可以一直 push 54 | - (IBAction)pushToDownloadedAction:(id)sender { 55 | } 56 | 57 | #pragma mark - life cycle 58 | 59 | //這邊我故意沒有放 [super viewDidLoad], 不然會跑到很多 mainviewcontroller 的東西 60 | - (void)viewDidLoad { 61 | self.title = @"已經下載的漫畫"; 62 | [self.listCollectionView registerNib:[UINib nibWithNibName:@"GalleryCell" bundle:nil] forCellWithReuseIdentifier:@"GalleryCell"]; 63 | } 64 | 65 | - (void)viewWillAppear:(BOOL)animated { 66 | [super viewWillAppear:animated]; 67 | [self.listCollectionView reloadData]; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /e-Hentai/HentaiDownloadCenter/HentaiDownloadBookOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiDownloadBookOperation.h 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/11. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "HentaiDownloadImageOperation.h" 12 | 13 | @interface HentaiDownloadBookOperation : NSOperation 14 | 15 | @property (nonatomic, strong) NSDictionary *bookInfo; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /e-Hentai/HentaiDownloadCenter/HentaiDownloadBookOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiDownloadBookOperation.m 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/11. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "HentaiDownloadBookOperation.h" 10 | 11 | @interface HentaiDownloadBookOperation () 12 | 13 | @property (nonatomic, assign) NSUInteger hentaiIndex; 14 | @property (nonatomic, strong) NSMutableArray *hentaiImageURLs; 15 | @property (nonatomic, strong) NSMutableDictionary *retryMap; 16 | @property (nonatomic, assign) NSUInteger failCount; 17 | @property (nonatomic, strong) NSMutableDictionary *hentaiResults; 18 | @property (nonatomic, readonly) NSString *hentaiKey; 19 | @property (nonatomic, strong) NSOperationQueue *hentaiQueue; 20 | @property (nonatomic, strong) NSString *maxHentaiCount; 21 | 22 | @property (nonatomic, assign) BOOL isExecuting; 23 | @property (nonatomic, assign) BOOL isFinished; 24 | 25 | @end 26 | 27 | @implementation HentaiDownloadBookOperation 28 | 29 | #pragma mark - Methods to Override 30 | 31 | - (BOOL)isConcurrent { 32 | return YES; 33 | } 34 | 35 | - (void)start { 36 | if ([self isCancelled]) { 37 | [self hentaiFinish]; 38 | return; 39 | } 40 | 41 | [self hentaiStart]; 42 | self.hentaiIndex = -1; 43 | self.hentaiImageURLs = [NSMutableArray array]; 44 | self.retryMap = [NSMutableDictionary dictionary]; 45 | self.failCount = 0; 46 | self.hentaiResults = [NSMutableDictionary dictionary]; 47 | self.hentaiQueue = [NSOperationQueue new]; 48 | [self.hentaiQueue setMaxConcurrentOperationCount:2]; 49 | self.maxHentaiCount = self.bookInfo[@"filecount"]; 50 | 51 | dispatch_async(dispatch_get_main_queue(), ^{ 52 | [self checkEndOfFile]; 53 | }); 54 | } 55 | 56 | + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { 57 | return YES; 58 | } 59 | 60 | #pragma mark - getter 61 | 62 | @dynamic hentaiKey; 63 | 64 | - (NSString *)hentaiKey { 65 | NSArray *splitStrings = [self.bookInfo[@"url"] componentsSeparatedByString:@"/"]; 66 | NSUInteger splitCount = [splitStrings count]; 67 | NSString *checkHentaiKey = [NSString stringWithFormat:@"%@-%@-%@", splitStrings[splitCount - 3], splitStrings[splitCount - 2], self.bookInfo[@"title"]]; 68 | return [checkHentaiKey stringByReplacingOccurrencesOfString:@"/" withString:@"-"]; 69 | } 70 | 71 | #pragma mark - HentaiDownloadImageOperationDelegate 72 | 73 | - (void)downloadResult:(NSString *)urlString heightOfSize:(CGFloat)height isSuccess:(BOOL)isSuccess { 74 | if (isSuccess) { 75 | self.hentaiResults[[urlString lastPathComponent]] = @(height); 76 | } 77 | else { 78 | NSNumber *retryCount = self.retryMap[urlString]; 79 | if (retryCount) { 80 | retryCount = @([retryCount integerValue] + 1); 81 | } 82 | else { 83 | retryCount = @(1); 84 | } 85 | self.retryMap[urlString] = retryCount; 86 | 87 | if ([retryCount integerValue] <= 3) { 88 | [self createNewOperation:urlString]; 89 | } 90 | else { 91 | self.failCount++; 92 | self.maxHentaiCount = [NSString stringWithFormat:@"%d", [self.maxHentaiCount integerValue] - 1]; 93 | [self.hentaiImageURLs removeObject:urlString]; 94 | } 95 | } 96 | } 97 | 98 | #pragma mark - operation status 99 | 100 | - (void)hentaiStart { 101 | self.isFinished = NO; 102 | self.isExecuting = YES; 103 | } 104 | 105 | - (void)hentaiFinish { 106 | [self.hentaiQueue cancelAllOperations]; 107 | self.isFinished = YES; 108 | self.isExecuting = NO; 109 | } 110 | 111 | #pragma mark - download methods 112 | 113 | //將要下載的圖片加到 queue 裡面 114 | - (void)preloadImages:(NSArray *)images { 115 | for (NSString *eachImageString in images) { 116 | [self createNewOperation:eachImageString]; 117 | } 118 | } 119 | 120 | //等待圖片下載完成 121 | - (void)waitingOnDownloadFinish { 122 | __weak HentaiDownloadBookOperation *weakSelf = self; 123 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 124 | [weakSelf.hentaiQueue waitUntilAllOperationsAreFinished]; 125 | if (weakSelf && ![self isCancelled]) { 126 | __strong HentaiDownloadBookOperation *strongSelf = weakSelf; 127 | dispatch_async(dispatch_get_main_queue(), ^{ 128 | [strongSelf checkEndOfFile]; 129 | }); 130 | } 131 | else { 132 | [self hentaiFinish]; 133 | } 134 | }); 135 | } 136 | 137 | //檢查是不是還有圖片需要下載 138 | - (void)checkEndOfFile { 139 | if ([self.hentaiImageURLs count] < [self.maxHentaiCount integerValue]) { 140 | self.hentaiIndex++; 141 | __weak HentaiDownloadBookOperation *weakSelf = self; 142 | [HentaiParser requestImagesAtURL:self.bookInfo[@"url"] atIndex:self.hentaiIndex completion: ^(HentaiParserStatus status, NSArray *images) { 143 | if (status && weakSelf && ![self isCancelled]) { 144 | __strong HentaiDownloadBookOperation *strongSelf = weakSelf; 145 | [strongSelf.hentaiImageURLs addObjectsFromArray:images]; 146 | [strongSelf preloadImages:images]; 147 | [strongSelf waitingOnDownloadFinish]; 148 | } 149 | else { 150 | [self hentaiFinish]; 151 | } 152 | }]; 153 | } 154 | else { 155 | if (![self isCancelled]) { 156 | NSDictionary *saveInfo = @{ @"hentaiKey":self.hentaiKey, @"images":self.hentaiImageURLs, @"hentaiResult":self.hentaiResults, @"hentaiInfo":self.bookInfo }; 157 | [HentaiSaveLibraryArray addObject:saveInfo]; 158 | 159 | //如果 cache 有暫存就殺光光 160 | [[[FilesManager cacheFolder] fcd:@"Hentai"] rd:self.hentaiKey]; 161 | [HentaiCacheLibraryDictionary removeObjectForKey:self.hentaiKey]; 162 | LWPForceWrite(); 163 | [[NSNotificationCenter defaultCenter] postNotificationName:HentaiDownloadSuccessNotification object:self.bookInfo[@"title"]]; 164 | [self hentaiFinish]; 165 | } 166 | else { 167 | [self hentaiFinish]; 168 | } 169 | } 170 | } 171 | 172 | #pragma mark - private 173 | 174 | - (void)createNewOperation:(NSString *)urlString { 175 | HentaiDownloadImageOperation *newOperation = [HentaiDownloadImageOperation new]; 176 | newOperation.downloadURLString = urlString; 177 | newOperation.isCacheOperation = NO; 178 | newOperation.hentaiKey = self.hentaiKey; 179 | newOperation.delegate = self; 180 | [self.hentaiQueue addOperation:newOperation]; 181 | } 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /e-Hentai/HentaiDownloadCenter/HentaiDownloadCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiDownloadCenter.h 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/11. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "HentaiDownloadBookOperation.h" 12 | 13 | #define HentaiDownloadSuccessNotification @"HentaiDownloadSuccessNotification" 14 | #define HentaiDownloadFailNotification @"HentaiDownloadFailNotification" 15 | 16 | @interface HentaiDownloadCenter : NSObject 17 | 18 | + (void)addBook:(NSDictionary *)bookInfo; 19 | + (BOOL)isDownloading:(NSDictionary *)bookInfo; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /e-Hentai/HentaiDownloadCenter/HentaiDownloadCenter.m: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiDownloadCenter.m 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/11. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "HentaiDownloadCenter.h" 10 | 11 | #import 12 | 13 | @implementation HentaiDownloadCenter 14 | 15 | #pragma mark - class method 16 | 17 | + (void)addBook:(NSDictionary *)bookInfo { 18 | BOOL isExist = NO; 19 | 20 | //如果下載過的話不給下 21 | for (NSDictionary *eachInfo in HentaiSaveLibraryArray) { 22 | if ([eachInfo[@"url"] isEqualToString:bookInfo[@"url"]]) { 23 | isExist = YES; 24 | break; 25 | } 26 | } 27 | 28 | //如果在 queue 裡面也不給下 29 | isExist = isExist | [self isDownloading:bookInfo]; 30 | 31 | if (isExist) { 32 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"不行~ O3O" message:@"你可能已經下載過或是正在下載中!" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil]; 33 | [alert show]; 34 | } 35 | else { 36 | HentaiDownloadBookOperation *newOperation = [HentaiDownloadBookOperation new]; 37 | newOperation.bookInfo = bookInfo; 38 | [[self allBooksOperationQueue] addOperation:newOperation]; 39 | } 40 | } 41 | 42 | + (BOOL)isDownloading:(NSDictionary *)bookInfo { 43 | BOOL isExist = NO; 44 | 45 | for (HentaiDownloadBookOperation *eachOperation in[[self allBooksOperationQueue] operations]) { 46 | if ([eachOperation.bookInfo[@"url"] isEqualToString:bookInfo[@"url"]]) { 47 | isExist = YES; 48 | break; 49 | } 50 | } 51 | return isExist; 52 | } 53 | 54 | #pragma mark - private 55 | 56 | + (NSOperationQueue *)allBooksOperationQueue { 57 | static dispatch_once_t onceToken; 58 | dispatch_once(&onceToken, ^{ 59 | NSOperationQueue *hentaiQueue = [NSOperationQueue new]; 60 | [hentaiQueue setMaxConcurrentOperationCount:2]; 61 | objc_setAssociatedObject(self, _cmd, hentaiQueue, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 62 | }); 63 | return objc_getAssociatedObject(self, _cmd); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /e-Hentai/HentaiDownloadCenter/HentaiDownloadImageOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiDownloadOperation.h 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/5. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol HentaiDownloadImageOperationDelegate; 12 | 13 | @interface HentaiDownloadImageOperation : NSOperation 14 | 15 | @property (nonatomic, weak) id delegate; 16 | @property (nonatomic, strong) NSString *downloadURLString; 17 | @property (nonatomic, strong) NSString *hentaiKey; 18 | @property (nonatomic, assign) BOOL isCacheOperation; 19 | 20 | @end 21 | 22 | @protocol HentaiDownloadImageOperationDelegate 23 | 24 | @required 25 | - (void)downloadResult:(NSString *)urlString heightOfSize:(CGFloat)height isSuccess:(BOOL)isSuccess; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /e-Hentai/HentaiDownloadCenter/HentaiDownloadImageOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiDownloadOperation.m 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/5. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "HentaiDownloadImageOperation.h" 10 | 11 | @interface HentaiDownloadImageOperation () 12 | 13 | @property (nonatomic, strong) NSMutableData *recvData; 14 | @property (nonatomic, assign) BOOL isExecuting; 15 | @property (nonatomic, assign) BOOL isFinished; 16 | 17 | @end 18 | 19 | @implementation HentaiDownloadImageOperation 20 | 21 | #pragma mark - Methods to Override 22 | 23 | - (BOOL)isConcurrent { 24 | return YES; 25 | } 26 | 27 | - (void)start { 28 | if ([self isCancelled]) { 29 | [self hentaiFinish]; 30 | return; 31 | } 32 | 33 | [self hentaiStart]; 34 | NSNumber *imageHeight = HentaiCacheLibraryDictionary[self.hentaiKey][[self.downloadURLString lastPathComponent]]; 35 | 36 | //從 imageHeight 的有無可以判斷這個檔案是否已經有了 37 | if (!imageHeight) { 38 | NSURL *url = [NSURL URLWithString:self.downloadURLString]; 39 | 40 | NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0f] delegate:self startImmediately:NO]; 41 | [conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 42 | [conn start]; 43 | } 44 | else { 45 | if (![self isCancelled]) { 46 | dispatch_sync(dispatch_get_main_queue(), ^{ 47 | [self.delegate downloadResult:self.downloadURLString heightOfSize:[imageHeight floatValue] isSuccess:YES]; 48 | [self hentaiFinish]; 49 | }); 50 | } 51 | } 52 | } 53 | 54 | + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { 55 | return YES; 56 | } 57 | 58 | #pragma mark - NSURLConnectionDelegate 59 | 60 | 61 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 62 | self.recvData = [NSMutableData data]; 63 | } 64 | 65 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 66 | if (![self isCancelled]) { 67 | [self.recvData appendData:data]; 68 | } 69 | else { 70 | [self hentaiFinish]; 71 | [connection cancel]; 72 | connection = nil; 73 | } 74 | } 75 | 76 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection { 77 | if (![self isCancelled]) { 78 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 79 | UIImage *image = [self resizeImageWithImage:[[UIImage alloc] initWithData:self.recvData]]; 80 | 81 | if (self.isCacheOperation) { 82 | [[[[FilesManager cacheFolder] fcd:@"Hentai"] fcd:self.hentaiKey] write:UIImageJPEGRepresentation(image, 0.6f) filename:[self.downloadURLString lastPathComponent]]; 83 | } 84 | else { 85 | [[[FilesManager documentFolder] fcd:self.hentaiKey] write:UIImageJPEGRepresentation(image, 0.6f) filename:[self.downloadURLString lastPathComponent]]; 86 | } 87 | 88 | //讓檔案轉存這件事情不擋線程 89 | dispatch_async(dispatch_get_main_queue(), ^{ 90 | [self.delegate downloadResult:self.downloadURLString heightOfSize:image.size.height isSuccess:YES]; 91 | [self hentaiFinish]; 92 | }); 93 | }); 94 | } 95 | [connection cancel]; 96 | connection = nil; 97 | } 98 | 99 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 100 | if (![self isCancelled]) { 101 | [self.delegate downloadResult:self.downloadURLString heightOfSize:-1 isSuccess:NO]; 102 | } 103 | [self hentaiFinish]; 104 | [connection cancel]; 105 | connection = nil; 106 | } 107 | 108 | #pragma mark - private 109 | 110 | - (void)hentaiStart { 111 | self.isFinished = NO; 112 | self.isExecuting = YES; 113 | } 114 | 115 | - (void)hentaiFinish { 116 | self.isFinished = YES; 117 | self.isExecuting = NO; 118 | } 119 | 120 | //計算符合螢幕 size 的新大小 121 | - (CGSize)calendarNewSize:(UIImage *)image { 122 | CGFloat oldWidth = image.size.width; 123 | CGFloat scaleFactor = [UIScreen mainScreen].bounds.size.height / oldWidth; 124 | CGFloat newHeight = image.size.height * scaleFactor; 125 | CGFloat newWidth = oldWidth * scaleFactor; 126 | return CGSizeMake(newWidth, newHeight); 127 | } 128 | 129 | //根據新的大小把圖片縮小, 原網站上面的圖片都過大 130 | - (UIImage *)resizeImageWithImage:(UIImage *)image { 131 | CGSize newSize = [self calendarNewSize:image]; 132 | UIGraphicsBeginImageContext(newSize); 133 | //retina 的圖片實在太大, 吃不消 所以先不 retina 試試 134 | //UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0); 135 | [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; 136 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 137 | UIGraphicsEndImageContext(); 138 | return newImage; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /e-Hentai/HentaiParser/HentaiParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiParser.h 3 | // TEST_2014_9_2 4 | // 5 | // Created by 啟倫 陳 on 2014/9/2. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | HentaiParserStatusFail, 13 | HentaiParserStatusSuccess 14 | } HentaiParserStatus; 15 | 16 | @interface HentaiParser : NSObject 17 | 18 | + (void)requestListAtIndex:(NSUInteger)index completion:(void (^)(HentaiParserStatus status, NSArray *listArray))completion; 19 | + (void)requestListAtFilterUrl:(NSString *)urlString completion:(void (^)(HentaiParserStatus status, NSArray *listArray))completion; 20 | + (void)requestImagesAtURL:(NSString *)urlString atIndex:(NSUInteger)index completion:(void (^)(HentaiParserStatus status, NSArray *images))completion; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /e-Hentai/HentaiSearchFilter/HentaiFilterView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiFilterView.h 3 | // e-Hentai 4 | // 5 | // Created by OptimusKe on 2014/9/28. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HentaiFilterView : UIView 12 | 13 | - (void)selectAll; 14 | - (NSArray *)filterResult; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /e-Hentai/HentaiSearchFilter/HentaiFilterView.m: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiFilterView.m 3 | // e-Hentai 4 | // 5 | // Created by OptimusKe on 2014/9/28. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "HentaiFilterView.h" 10 | #import "HentaiSearchFilter.h" 11 | 12 | #define colorDoujinshi [UIColor colorWithRed:251.0 / 255.0 green:99.0 / 255.0 blue:102.0 / 255.0 alpha:1] 13 | #define colorManga [UIColor colorWithRed:252.0 / 255.0 green:194.0 / 255.0 blue:82.0 / 255.0 alpha:1] 14 | #define colorArtistcg [UIColor colorWithRed:238.0 / 255.0 green:230.0 / 255.0 blue:102.0 / 255.0 alpha:1] 15 | #define colorGamecg [UIColor colorWithRed:192.0 / 255.0 green:129.0 / 255.0 blue:127.0 / 255.0 alpha:1] 16 | #define colorWestern [UIColor colorWithRed:170.0 / 255.0 green:255.0 / 255.0 blue:87.0 / 255.0 alpha:1] 17 | #define colorNonh [UIColor colorWithRed:132.0 / 255.0 green:199.0 / 255.0 blue:255.0 / 255.0 alpha:1] 18 | #define colorImageset [UIColor colorWithRed:108.0 / 255.0 green:96.0 / 255.0 blue:255.0 / 255.0 alpha:1] 19 | #define colorCosplay [UIColor colorWithRed:144.0 / 255.0 green:97.0 / 255.0 blue:181.0 / 255.0 alpha:1] 20 | #define colorAsianporn [UIColor colorWithRed:245.0 / 255.0 green:175.0 / 255.0 blue:246.0 / 255.0 alpha:1] 21 | #define colorMisc [UIColor colorWithRed:219.0 / 255.0 green:219.0 / 255.0 blue:219.0 / 255.0 alpha:1] 22 | #define colorAll [UIColor grayColor] 23 | 24 | @interface HentaiFilterView () 25 | { 26 | NSMutableArray *filterEnableArray; 27 | } 28 | 29 | 30 | @end 31 | 32 | @implementation HentaiFilterView 33 | 34 | - (id)initWithFrame:(CGRect)frame { 35 | self = [super initWithFrame:frame]; 36 | if (self) { 37 | // Initialization code 38 | self.backgroundColor = [UIColor blackColor]; 39 | [self setButtons]; 40 | } 41 | return self; 42 | } 43 | 44 | - (void)selectAll { 45 | for (int i = 0; i < filterEnableArray.count; i++) { 46 | [filterEnableArray replaceObjectAtIndex:i withObject:@(YES)]; 47 | } 48 | 49 | for (UIButton *btn in self.subviews) { 50 | [self setButtonEnableStyle:btn enable:YES]; 51 | } 52 | } 53 | 54 | - (NSArray *)filterResult { 55 | NSMutableArray *resultArray = [NSMutableArray array]; 56 | 57 | for (int i = 0; i < filterEnableArray.count; i++) { 58 | NSNumber *filterNum = [filterEnableArray objectAtIndex:i]; 59 | if ([filterNum boolValue]) { 60 | [resultArray addObject:@(i)]; 61 | } 62 | } 63 | 64 | return resultArray; 65 | } 66 | 67 | #pragma mark - private 68 | 69 | 70 | - (void)setButtons { 71 | filterEnableArray = [NSMutableArray arrayWithCapacity:10]; 72 | 73 | for (int i = 0; i < 10; i++) { 74 | CGFloat x = (i % 2 == 0) ? 0 : CGRectGetWidth(self.frame) / 2; 75 | CGFloat y = (i / 2) * 40; 76 | 77 | //init all Tag YES 78 | NSNumber *tapTag = @(YES); 79 | [filterEnableArray insertObject:tapTag atIndex:i]; 80 | 81 | UIButton *filterBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, CGRectGetWidth(self.frame) / 2, 40)]; 82 | filterBtn.tag = i; 83 | filterBtn.titleLabel.textColor = [UIColor whiteColor]; 84 | NSNumber *filterTag = @(i); 85 | filterBtn.backgroundColor = [self colorMapping:filterTag]; 86 | [filterBtn setTitle:[self titleMapping:filterTag] forState:UIControlStateNormal]; 87 | [filterBtn setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted]; 88 | [filterBtn addTarget:self action:@selector(buttonPress:) forControlEvents:UIControlEventTouchUpInside]; 89 | [self addSubview:filterBtn]; 90 | } 91 | } 92 | 93 | - (UIColor *)colorMapping:(NSNumber *)filterTag { 94 | NSDictionary *mapping = @{ @(HentaiFilterTypeDoujinshi) : colorDoujinshi, 95 | @(HentaiFilterTypeManga) : colorManga, 96 | @(HentaiFilterTypeArtistcg) : colorArtistcg, 97 | @(HentaiFilterTypeGamecg) : colorGamecg, 98 | @(HentaiFilterTypeWestern) : colorWestern, 99 | @(HentaiFilterTypeNonh) : colorNonh, 100 | @(HentaiFilterTypeImagesets) : colorImageset, 101 | @(HentaiFilterTypeCosplay) : colorCosplay, 102 | @(HentaiFilterTypeAsianporn) : colorAsianporn, 103 | @(HentaiFilterTypeMisc) : colorMisc }; 104 | return mapping[filterTag] ? mapping[filterTag] : colorAll; 105 | } 106 | 107 | - (NSString *)titleMapping:(NSNumber *)filterTag { 108 | NSDictionary *mapping = @{ @(HentaiFilterTypeDoujinshi) : @"Doujinshi", 109 | @(HentaiFilterTypeManga) : @"Manga", 110 | @(HentaiFilterTypeArtistcg) : @"Artistcg", 111 | @(HentaiFilterTypeGamecg) : @"Gamecg", 112 | @(HentaiFilterTypeWestern) : @"Western", 113 | @(HentaiFilterTypeNonh) : @"Nonh", 114 | @(HentaiFilterTypeImagesets) : @"Imageset", 115 | @(HentaiFilterTypeCosplay) : @"Cosplay", 116 | @(HentaiFilterTypeAsianporn) : @"Asianporn", 117 | @(HentaiFilterTypeMisc) : @"Misc" }; 118 | return mapping[filterTag] ? mapping[filterTag] : @"All"; 119 | } 120 | 121 | - (void)setButtonEnableStyle:(UIButton *)btn enable:(BOOL)enable { 122 | NSNumber *filterTag = @(btn.tag); 123 | if (enable) { 124 | btn.backgroundColor = [self colorMapping:filterTag]; 125 | [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 126 | } 127 | else { 128 | btn.backgroundColor = [UIColor blackColor]; 129 | [btn setTitleColor:[self colorMapping:filterTag] forState:UIControlStateNormal]; 130 | } 131 | } 132 | 133 | - (void)buttonPress:(UIButton *)btn { 134 | BOOL enable = [[filterEnableArray objectAtIndex:btn.tag] boolValue]; 135 | enable = !enable; 136 | [filterEnableArray replaceObjectAtIndex:btn.tag withObject:@(enable)]; 137 | [self setButtonEnableStyle:btn enable:enable]; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /e-Hentai/HentaiSearchFilter/HentaiSearchFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiSearchFilter.h 3 | // CoreGraphicsTest 4 | // 5 | // Created by OptimusKe on 2014/9/26. 6 | // Copyright (c) 2014年 Jack. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM (NSInteger, HentaiFilterType) { 12 | HentaiFilterTypeDoujinshi = 0, 13 | HentaiFilterTypeManga, 14 | HentaiFilterTypeArtistcg, 15 | HentaiFilterTypeGamecg, 16 | HentaiFilterTypeWestern, 17 | HentaiFilterTypeNonh, 18 | HentaiFilterTypeImagesets, 19 | HentaiFilterTypeCosplay, 20 | HentaiFilterTypeAsianporn, 21 | HentaiFilterTypeMisc 22 | }; 23 | 24 | @interface HentaiSearchFilter : NSObject 25 | 26 | + (NSString *)searchFilterUrlByKeyword:(NSString *)searchWord 27 | filterArray:(NSArray *)filterArray 28 | baseUrl:(NSString *)baseUrl; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /e-Hentai/HentaiSearchFilter/HentaiSearchFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiSearchFilter.m 3 | // CoreGraphicsTest 4 | // 5 | // Created by OptimusKe on 2014/9/26. 6 | // Copyright (c) 2014年 Jack. All rights reserved. 7 | // 8 | 9 | #import "HentaiSearchFilter.h" 10 | 11 | @implementation HentaiSearchFilter 12 | 13 | + (NSString *)searchFilterUrlByKeyword:(NSString *)searchWord 14 | filterArray:(NSArray *)filterArray 15 | baseUrl:(NSString *)baseUrl { 16 | NSString *filterUrl = [[NSString alloc] initWithString:baseUrl]; 17 | 18 | //do nothing 19 | if ([searchWord isEqualToString:@""] && filterArray.count == 0) { 20 | return filterUrl; 21 | } 22 | 23 | 24 | NSDictionary *filterMapping = @{ @(HentaiFilterTypeDoujinshi) : @"f_doujinshi=1", 25 | @(HentaiFilterTypeManga) : @"f_manga=1", 26 | @(HentaiFilterTypeArtistcg) : @"f_artistcg=1", 27 | @(HentaiFilterTypeGamecg) : @"f_gamecg=1", 28 | @(HentaiFilterTypeWestern) : @"f_western=1", 29 | @(HentaiFilterTypeNonh) : @"f_non-h=1", 30 | @(HentaiFilterTypeImagesets) : @"f_imageset=1", 31 | @(HentaiFilterTypeCosplay) : @"f_cosplay=1", 32 | @(HentaiFilterTypeAsianporn) : @"f_asianporn=1", 33 | @(HentaiFilterTypeMisc) : @"f_misc=1" }; 34 | 35 | if (filterArray.count != 0 || filterArray.count != 10) { 36 | for (NSNumber *filterNum in filterArray) { 37 | filterUrl = [filterUrl stringByAppendingString:[NSString stringWithFormat:@"&%@", filterMapping[filterNum]]]; 38 | } 39 | } 40 | 41 | if (![searchWord isEqualToString:@""]) { 42 | filterUrl = [filterUrl stringByAppendingString:[NSString stringWithFormat:@"&f_search=%@", searchWord]]; 43 | } 44 | 45 | //apply 46 | filterUrl = [filterUrl stringByAppendingString:@"&f_apply=Apply+Filter"]; 47 | 48 | return filterUrl; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /e-Hentai/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /e-Hentai/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /e-Hentai/MainViewController/GalleryCell/CategoryTitle.h: -------------------------------------------------------------------------------- 1 | // 2 | // CategoryTitle.h 3 | // e-Hentai 4 | // 5 | // Created by Jack on 2014/9/5. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CategoryTitle : UIView 12 | { 13 | NSString *categoryString; 14 | UILabel *categoryLabel; 15 | } 16 | 17 | - (void)setCategoryStr:(NSString *)category; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/GalleryCell/CategoryTitle.m: -------------------------------------------------------------------------------- 1 | // 2 | // CategoryTitle.m 3 | // e-Hentai 4 | // 5 | // Created by Jack on 2014/9/5. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "CategoryTitle.h" 10 | 11 | #define colorDoujinshi [UIColor colorWithRed:251.0 / 255.0 green:99.0 / 255.0 blue:102.0 / 255.0 alpha:1] 12 | #define colorManga [UIColor colorWithRed:252.0 / 255.0 green:194.0 / 255.0 blue:82.0 / 255.0 alpha:1] 13 | #define colorArtistcg [UIColor colorWithRed:238.0 / 255.0 green:230.0 / 255.0 blue:102.0 / 255.0 alpha:1] 14 | #define colorGamecg [UIColor colorWithRed:192.0 / 255.0 green:129.0 / 255.0 blue:127.0 / 255.0 alpha:1] 15 | #define colorWestern [UIColor colorWithRed:170.0 / 255.0 green:255.0 / 255.0 blue:87.0 / 255.0 alpha:1] 16 | #define colorNonh [UIColor colorWithRed:132.0 / 255.0 green:199.0 / 255.0 blue:255.0 / 255.0 alpha:1] 17 | #define colorImageset [UIColor colorWithRed:108.0 / 255.0 green:96.0 / 255.0 blue:255.0 / 255.0 alpha:1] 18 | #define colorCosplay [UIColor colorWithRed:144.0 / 255.0 green:97.0 / 255.0 blue:181.0 / 255.0 alpha:1] 19 | #define colorAsianporn [UIColor colorWithRed:245.0 / 255.0 green:175.0 / 255.0 blue:246.0 / 255.0 alpha:1] 20 | #define colorMisc [UIColor colorWithRed:219.0 / 255.0 green:219.0 / 255.0 blue:219.0 / 255.0 alpha:1] 21 | 22 | //Flat Blue 23 | #define CORLOR_TEXT [UIColor colorWithRed:52.0 / 255.0 green:152.0 / 255.0 blue:219.0 / 255.0 alpha:1] 24 | 25 | @implementation CategoryTitle 26 | 27 | 28 | - (id)initWithCoder:(NSCoder *)aDecoder { 29 | self = [super initWithCoder:aDecoder]; 30 | if (self) { 31 | self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.7]; 32 | categoryString = @""; 33 | categoryLabel = [UILabel new]; 34 | [self addSubview:categoryLabel]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)setCategoryStr:(NSString *)category { 40 | categoryString = category; 41 | categoryLabel.textColor = [self colorMapping:category]; 42 | [self layoutSubviews]; 43 | } 44 | 45 | - (UIColor *)colorMapping:(NSString *)category { 46 | NSDictionary *mapping = @{ @"Doujinshi" : colorDoujinshi, 47 | @"Manga" : colorManga, 48 | @"Artist CG Sets" : colorArtistcg, 49 | @"Game CG Sets" : colorGamecg, 50 | @"Western" : colorWestern, 51 | @"Non-H" : colorNonh, 52 | @"Image Sets" : colorImageset, 53 | @"Cosplay" : colorCosplay, 54 | @"Asian Porn" : colorAsianporn }; 55 | return mapping[category] ? : colorMisc; 56 | } 57 | 58 | - (void)layoutSubviews { 59 | CGRect labelFrame = CGRectOffset(self.bounds, 5, 0); //padding 5 60 | categoryLabel.frame = labelFrame; 61 | categoryLabel.backgroundColor = [UIColor clearColor]; 62 | categoryLabel.font = [UIFont systemFontOfSize:14.0]; 63 | categoryLabel.text = categoryString; 64 | 65 | self.layer.cornerRadius = CGRectGetHeight(self.bounds) / 4; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/GalleryCell/GalleryCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // GalleryCell.h 3 | // e-Hentai 4 | // 5 | // Created by Jack on 2014/9/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define imageMode @"IMAGE_MODE" 12 | 13 | @class CategoryTitle; 14 | @class RatingStar; 15 | 16 | @interface GalleryCell : UICollectionViewCell 17 | 18 | @property (weak, nonatomic) IBOutlet UILabel *cellLabel; 19 | @property (weak, nonatomic) IBOutlet UIImageView *cellImageView; 20 | @property (weak, nonatomic) IBOutlet CategoryTitle *cellCategory; 21 | @property (weak, nonatomic) IBOutlet RatingStar *cellStar; 22 | 23 | //設定資料 24 | - (void)setGalleryDict:(NSDictionary *)dataDict; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/GalleryCell/GalleryCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // GalleryCell.m 3 | // e-Hentai 4 | // 5 | // Created by Jack on 2014/9/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "GalleryCell.h" 10 | #import "UIImageView+WebCache.h" 11 | #import "CategoryTitle.h" 12 | #import "RatingStar.h" 13 | 14 | @implementation GalleryCell 15 | 16 | 17 | 18 | #pragma mark - 19 | 20 | //設定資料 21 | - (void)setGalleryDict:(NSDictionary *)dataDict { 22 | self.cellLabel.text = dataDict[@"title"]; 23 | 24 | 25 | BOOL enableImageMode = [dataDict[imageMode] boolValue]; 26 | 27 | NSString *imgUrl = @"http://i.imgur.com/1gzbPf1.jpg"; //貓貓圖(公司用) 28 | 29 | if (enableImageMode) { 30 | imgUrl = dataDict[@"thumb"]; //(真的H縮圖) 31 | } 32 | 33 | [self.cellImageView sd_setImageWithURL:[NSURL URLWithString:imgUrl] 34 | placeholderImage:nil 35 | options:SDWebImageRefreshCached]; 36 | 37 | [self.cellCategory setCategoryStr:dataDict[@"category"]]; 38 | [self.cellStar setStar:dataDict[@"rating"]]; 39 | } 40 | 41 | - (void)layoutSubviews { 42 | //Fit並置中 43 | self.cellImageView.contentMode = UIViewContentModeScaleAspectFit; 44 | self.cellImageView.clipsToBounds = YES; 45 | self.cellImageView.center = CGPointMake(self.cellImageView.center.x, CGRectGetMidY(self.bounds)); 46 | self.layer.cornerRadius = CGRectGetHeight(self.cellCategory.frame) / 4; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/GalleryCell/GalleryCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/GalleryCell/RatingStar.h: -------------------------------------------------------------------------------- 1 | // 2 | // RatingStar.h 3 | // e-Hentai 4 | // 5 | // Created by Jack on 2014/9/5. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RatingStar : UIView 12 | { 13 | NSString *starString; 14 | } 15 | 16 | - (void)setStar:(NSString *)star; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/GalleryCell/RatingStar.m: -------------------------------------------------------------------------------- 1 | // 2 | // RatingStar.m 3 | // e-Hentai 4 | // 5 | // Created by Jack on 2014/9/5. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "RatingStar.h" 10 | 11 | 12 | 13 | @implementation RatingStar 14 | 15 | 16 | - (id)initWithCoder:(NSCoder *)aDecoder { 17 | self = [super initWithCoder:aDecoder]; 18 | if (self) { 19 | self.backgroundColor = [UIColor clearColor]; 20 | starString = @""; 21 | } 22 | return self; 23 | } 24 | 25 | - (void)setStar:(NSString *)star { 26 | starString = star; 27 | [self setNeedsDisplay]; 28 | } 29 | 30 | - (void)drawRect:(CGRect)rect { 31 | 32 | int aSize = CGRectGetWidth(rect); 33 | const CGFloat color[4] = { 255.0 / 255.0, 215.0 / 255.0, 0.0, 1.0 }; // Gold 34 | CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 35 | CGColorRef aColor = CGColorCreate(colorspace, color); 36 | CGContextRef context = UIGraphicsGetCurrentContext(); 37 | CGContextSetLineWidth(context, aSize); 38 | CGFloat xCenter = CGRectGetMidX(rect); 39 | CGFloat yCenter = CGRectGetMidY(rect); 40 | 41 | 42 | float w = CGRectGetWidth(rect); //星形寬 43 | double r = w / 2.0; 44 | float flip = -1.0; 45 | 46 | 47 | CGContextSetFillColorWithColor(context, aColor); 48 | CGContextSetStrokeColorWithColor(context, aColor); 49 | 50 | double theta = 2.0 * M_PI * (2.0 / 5.0); // 144 degrees 51 | 52 | CGContextMoveToPoint(context, xCenter, r * flip + yCenter); 53 | 54 | for (NSUInteger k = 1; k < 5; k++) { 55 | float x = r * sin(k * theta); 56 | float y = r * cos(k * theta); 57 | CGContextAddLineToPoint(context, x + xCenter, y * flip + yCenter); 58 | } 59 | 60 | CGContextClosePath(context); 61 | CGContextFillPath(context); 62 | 63 | CGFloat fontSize = CGRectGetWidth(rect) / 2; 64 | 65 | NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 66 | style.alignment = NSTextAlignmentCenter; 67 | 68 | NSDictionary *attributes = @{ NSFontAttributeName:[UIFont systemFontOfSize:fontSize], 69 | NSForegroundColorAttributeName:[UIColor blackColor], 70 | NSParagraphStyleAttributeName:style }; 71 | 72 | NSString *star = [starString substringToIndex:1]; 73 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:star attributes:attributes]; 74 | 75 | 76 | [attrStr drawInRect:CGRectMake(CGRectGetMidX(rect) - fontSize / 2, 77 | CGRectGetMidY(rect) - fontSize / 2, 78 | fontSize, 79 | fontSize)]; 80 | CGColorRelease(aColor); 81 | CGColorSpaceRelease(colorspace); 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/MainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.h 3 | // TEST_2014_9_2 4 | // 5 | // Created by 啟倫 陳 on 2014/9/2. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "HentaiParser.h" 12 | #import "GalleryCell.h" 13 | #import "HentaiNavigationController.h" 14 | #import "PhotoViewController.h" 15 | #import "FakeViewController.h" 16 | 17 | @interface MainViewController : UIViewController 18 | 19 | @property (weak, nonatomic) IBOutlet UICollectionView *listCollectionView; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /e-Hentai/MainViewController/MainViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /e-Hentai/PhotoViewController/HentaiPhotoCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiPhotoCell.h 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HentaiPhotoCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *hentaiImageView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /e-Hentai/PhotoViewController/HentaiPhotoCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // HentaiPhotoCell.m 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/9/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "HentaiPhotoCell.h" 10 | 11 | @implementation HentaiPhotoCell 12 | 13 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 14 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 15 | if (self) { 16 | NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil]; 17 | self = arrayOfViews[0]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)layoutSubviews { 23 | [super layoutSubviews]; 24 | self.hentaiImageView.frame = self.bounds; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /e-Hentai/PhotoViewController/HentaiPhotoCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /e-Hentai/PhotoViewController/PhotoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoViewController.h 3 | // TEST_2014_9_2 4 | // 5 | // Created by 啟倫 陳 on 2014/9/3. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "HentaiNavigationController.h" 12 | #import "FakeViewController.h" 13 | #import "HentaiPhotoCell.h" 14 | #import "HentaiDownloadImageOperation.h" 15 | 16 | @interface PhotoViewController : UIViewController 17 | 18 | @property (nonatomic, strong) NSDictionary *hentaiInfo; 19 | 20 | @property (weak, nonatomic) IBOutlet UITableView *hentaiTableView; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /e-Hentai/PhotoViewController/PhotoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/FilesManager/FMStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMStream.h 3 | // TycheToolsV2 4 | // 5 | // Created by 啟倫 陳 on 2014/6/30. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FMStream : NSObject 12 | 13 | @property (nonatomic, strong) NSString *basePath; 14 | @property (nonatomic, strong) NSMutableArray *subPaths; 15 | 16 | @end 17 | 18 | @interface FMStream (Information) 19 | 20 | - (NSArray *)listFiles; 21 | - (NSArray *)listFolders; 22 | - (NSString *)currentPath; 23 | 24 | @end 25 | 26 | @interface FMStream (Folder) 27 | 28 | - (FMStream *)cdpp; 29 | - (FMStream *)cd:(NSString *)folder; 30 | - (FMStream *)fcd:(NSString *)folder; 31 | 32 | - (FMStream *)md:(NSString *)folder; 33 | - (FMStream *)rd:(NSString *)folder; 34 | 35 | - (void)moveToPath:(NSString *)toPath; 36 | 37 | @end 38 | 39 | @interface FMStream (IO) 40 | 41 | - (BOOL)write:(NSData *)data filename:(NSString *)name; 42 | - (NSData *)read:(NSString *)name; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/FilesManager/FMStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMStream.m 3 | // TycheToolsV2 4 | // 5 | // Created by 啟倫 陳 on 2014/6/30. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "FMStream.h" 10 | 11 | @implementation FMStream 12 | 13 | - (id)init { 14 | self = [super init]; 15 | if (self) { 16 | self.subPaths = [NSMutableArray array]; 17 | } 18 | return self; 19 | } 20 | 21 | - (NSString *)tmpPath:(NSString *)folder { 22 | NSMutableArray *tmpSubPaths = [NSMutableArray arrayWithArray:self.subPaths]; 23 | [tmpSubPaths addObject:folder]; 24 | return [self.basePath stringByAppendingPathComponent:[tmpSubPaths componentsJoinedByString:@"/"]]; 25 | } 26 | 27 | @end 28 | 29 | @implementation FMStream (Information) 30 | 31 | - (NSArray *)listFiles { 32 | NSFileManager *fileManager = [NSFileManager defaultManager]; 33 | NSArray *itemsArray = [fileManager contentsOfDirectoryAtPath:[self currentPath] error:nil]; 34 | NSMutableArray *filesArray = [NSMutableArray array]; 35 | BOOL isFolder; 36 | 37 | for (NSString *item in itemsArray) { 38 | NSString *itempath = [[self currentPath] stringByAppendingPathComponent:item]; 39 | [fileManager fileExistsAtPath:itempath isDirectory:(&isFolder)]; 40 | 41 | if (!isFolder) { 42 | [filesArray addObject:item]; 43 | } 44 | } 45 | return filesArray; 46 | } 47 | 48 | - (NSArray *)listFolders { 49 | NSFileManager *fileManager = [NSFileManager defaultManager]; 50 | NSArray *itemsArray = [fileManager contentsOfDirectoryAtPath:[self currentPath] error:nil]; 51 | NSMutableArray *foldersArray = [NSMutableArray array]; 52 | BOOL isFolder; 53 | 54 | for (NSString *item in itemsArray) { 55 | NSString *itempath = [[self currentPath] stringByAppendingPathComponent:item]; 56 | [fileManager fileExistsAtPath:itempath isDirectory:(&isFolder)]; 57 | 58 | if (isFolder) { 59 | [foldersArray addObject:item]; 60 | } 61 | } 62 | return foldersArray; 63 | } 64 | 65 | - (NSString *)currentPath { 66 | return [self.basePath stringByAppendingPathComponent:[self.subPaths componentsJoinedByString:@"/"]]; 67 | } 68 | 69 | @end 70 | 71 | 72 | @implementation FMStream (Folder) 73 | 74 | - (FMStream *)cdpp { 75 | [self.subPaths removeLastObject]; 76 | return self; 77 | } 78 | 79 | - (FMStream *)cd:(NSString *)folder { 80 | NSFileManager *fileManager = [NSFileManager defaultManager]; 81 | 82 | if ([fileManager fileExistsAtPath:[self tmpPath:folder]]) { 83 | [self.subPaths addObject:folder]; 84 | return self; 85 | } 86 | else { 87 | return nil; 88 | } 89 | } 90 | 91 | - (FMStream *)fcd:(NSString *)folder { 92 | NSFileManager *fileManager = [NSFileManager defaultManager]; 93 | 94 | if ([fileManager fileExistsAtPath:[self tmpPath:folder]]) { 95 | [self.subPaths addObject:folder]; 96 | } 97 | else { 98 | [[self md:folder] cd:folder]; 99 | } 100 | return self; 101 | } 102 | 103 | - (FMStream *)md:(NSString *)folder { 104 | NSFileManager *fileManager = [NSFileManager defaultManager]; 105 | 106 | if (![fileManager fileExistsAtPath:[self tmpPath:folder]]) { 107 | if ([[NSFileManager defaultManager] createDirectoryAtPath:[self tmpPath:folder] withIntermediateDirectories:NO attributes:nil error:nil]) { 108 | return self; 109 | } 110 | } 111 | return nil; 112 | } 113 | 114 | - (FMStream *)rd:(NSString *)folder { 115 | NSFileManager *fileManager = [NSFileManager defaultManager]; 116 | 117 | if ([fileManager fileExistsAtPath:[self tmpPath:folder]]) { 118 | if ([fileManager removeItemAtPath:[self tmpPath:folder] error:nil]) { 119 | return self; 120 | } 121 | } 122 | return nil; 123 | } 124 | 125 | - (void)moveToPath:(NSString *)toPath { 126 | NSFileManager *fileManager = [NSFileManager defaultManager]; 127 | [fileManager moveItemAtPath:self.currentPath toPath:toPath error:nil]; 128 | } 129 | 130 | @end 131 | 132 | 133 | @implementation FMStream (IO) 134 | 135 | - (BOOL)write:(NSData *)data filename:(NSString *)name { 136 | return [data writeToFile:[[self currentPath] stringByAppendingPathComponent:name] atomically:YES]; 137 | } 138 | 139 | - (NSData *)read:(NSString *)name { 140 | return [[NSFileManager defaultManager] contentsAtPath:[[self currentPath] stringByAppendingPathComponent:name]]; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/FilesManager/FilesManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // FilesManager.h 3 | // TycheToolsV2 4 | // 5 | // Created by 啟倫 陳 on 2014/6/30. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "FMStream.h" 10 | 11 | @interface FilesManager : FMStream 12 | 13 | + (FMStream *)documentFolder; 14 | + (FMStream *)resourceFolder; 15 | + (FMStream *)cacheFolder; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/FilesManager/FilesManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // FilesManager.m 3 | // TycheToolsV2 4 | // 5 | // Created by 啟倫 陳 on 2014/6/30. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "FilesManager.h" 10 | 11 | @implementation FilesManager 12 | 13 | #pragma mark - class method 14 | 15 | + (FMStream *)documentFolder { 16 | FMStream *newStream = [FMStream new]; 17 | newStream.basePath = [self documentFolderPathString]; 18 | return newStream; 19 | } 20 | 21 | + (FMStream *)resourceFolder { 22 | FMStream *newStream = [FMStream new]; 23 | newStream.basePath = [self resourceFolderPathString]; 24 | return newStream; 25 | } 26 | 27 | + (FMStream *)cacheFolder { 28 | FMStream *newStream = [FMStream new]; 29 | newStream.basePath = [self cacheFolderPathString]; 30 | return newStream; 31 | } 32 | 33 | #pragma mark - private 34 | 35 | + (NSString *)documentFolderPathString { 36 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 37 | return paths[0]; 38 | } 39 | 40 | + (NSString *)resourceFolderPathString { 41 | return [[NSBundle mainBundle] bundlePath]; 42 | } 43 | 44 | + (NSString *)cacheFolderPathString { 45 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 46 | return paths[0]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/Hpple/TFHpple.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFHpple.h 3 | // Hpple 4 | // 5 | // Created by Geoffrey Grosenbach on 1/31/09. 6 | // 7 | // Copyright (c) 2009 Topfunky Corporation, http://topfunky.com 8 | // 9 | // MIT LICENSE 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | 31 | #import 32 | 33 | #import "TFHppleElement.h" 34 | 35 | @interface TFHpple : NSObject 36 | 37 | - (id) initWithData:(NSData *)theData encoding:(NSString *)encoding isXML:(BOOL)isDataXML; 38 | - (id) initWithData:(NSData *)theData isXML:(BOOL)isDataXML; 39 | - (id) initWithXMLData:(NSData *)theData encoding:(NSString *)encoding; 40 | - (id) initWithXMLData:(NSData *)theData; 41 | - (id) initWithHTMLData:(NSData *)theData encoding:(NSString *)encoding; 42 | - (id) initWithHTMLData:(NSData *)theData; 43 | 44 | + (TFHpple *) hppleWithData:(NSData *)theData encoding:(NSString *)encoding isXML:(BOOL)isDataXML; 45 | + (TFHpple *) hppleWithData:(NSData *)theData isXML:(BOOL)isDataXML; 46 | + (TFHpple *) hppleWithXMLData:(NSData *)theData encoding:(NSString *)encoding; 47 | + (TFHpple *) hppleWithXMLData:(NSData *)theData; 48 | + (TFHpple *) hppleWithHTMLData:(NSData *)theData encoding:(NSString *)encoding; 49 | + (TFHpple *) hppleWithHTMLData:(NSData *)theData; 50 | 51 | - (NSArray *) searchWithXPathQuery:(NSString *)xPathOrCSS; 52 | - (TFHppleElement *) peekAtSearchWithXPathQuery:(NSString *)xPathOrCSS; 53 | 54 | @property (nonatomic, readonly) NSData * data; 55 | @property (nonatomic, readonly) NSString * encoding; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/Hpple/TFHpple.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFHpple.m 3 | // Hpple 4 | // 5 | // Created by Geoffrey Grosenbach on 1/31/09. 6 | // 7 | // Copyright (c) 2009 Topfunky Corporation, http://topfunky.com 8 | // 9 | // MIT LICENSE 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | #import "TFHpple.h" 31 | #import "XPathQuery.h" 32 | 33 | @interface TFHpple () 34 | { 35 | NSData * data; 36 | NSString * encoding; 37 | BOOL isXML; 38 | } 39 | 40 | @end 41 | 42 | 43 | @implementation TFHpple 44 | 45 | @synthesize data; 46 | @synthesize encoding; 47 | 48 | 49 | - (id) initWithData:(NSData *)theData encoding:(NSString *)theEncoding isXML:(BOOL)isDataXML 50 | { 51 | if (!(self = [super init])) { 52 | return nil; 53 | } 54 | 55 | data = theData; 56 | encoding = theEncoding; 57 | isXML = isDataXML; 58 | 59 | return self; 60 | } 61 | 62 | - (id) initWithData:(NSData *)theData isXML:(BOOL)isDataXML 63 | { 64 | return [self initWithData:theData encoding:nil isXML:isDataXML]; 65 | } 66 | 67 | - (id) initWithXMLData:(NSData *)theData encoding:(NSString *)theEncoding 68 | { 69 | return [self initWithData:theData encoding:theEncoding isXML:YES]; 70 | } 71 | 72 | - (id) initWithXMLData:(NSData *)theData 73 | { 74 | return [self initWithData:theData encoding:nil isXML:YES]; 75 | } 76 | 77 | - (id) initWithHTMLData:(NSData *)theData encoding:(NSString *)theEncoding 78 | { 79 | return [self initWithData:theData encoding:theEncoding isXML:NO]; 80 | } 81 | 82 | - (id) initWithHTMLData:(NSData *)theData 83 | { 84 | return [self initWithData:theData encoding:nil isXML:NO]; 85 | } 86 | 87 | + (TFHpple *) hppleWithData:(NSData *)theData encoding:(NSString *)theEncoding isXML:(BOOL)isDataXML { 88 | return [[[self class] alloc] initWithData:theData encoding:theEncoding isXML:isDataXML]; 89 | } 90 | 91 | + (TFHpple *) hppleWithData:(NSData *)theData isXML:(BOOL)isDataXML { 92 | return [[self class] hppleWithData:theData encoding:nil isXML:isDataXML]; 93 | } 94 | 95 | + (TFHpple *) hppleWithHTMLData:(NSData *)theData encoding:(NSString *)theEncoding { 96 | return [[self class] hppleWithData:theData encoding:theEncoding isXML:NO]; 97 | } 98 | 99 | + (TFHpple *) hppleWithHTMLData:(NSData *)theData { 100 | return [[self class] hppleWithData:theData encoding:nil isXML:NO]; 101 | } 102 | 103 | + (TFHpple *) hppleWithXMLData:(NSData *)theData encoding:(NSString *)theEncoding { 104 | return [[self class] hppleWithData:theData encoding:theEncoding isXML:YES]; 105 | } 106 | 107 | + (TFHpple *) hppleWithXMLData:(NSData *)theData { 108 | return [[self class] hppleWithData:theData encoding:nil isXML:YES]; 109 | } 110 | 111 | #pragma mark - 112 | 113 | // Returns all elements at xPath. 114 | - (NSArray *) searchWithXPathQuery:(NSString *)xPathOrCSS 115 | { 116 | NSArray * detailNodes = nil; 117 | if (isXML) { 118 | detailNodes = PerformXMLXPathQueryWithEncoding(data, xPathOrCSS, encoding); 119 | } else { 120 | detailNodes = PerformHTMLXPathQueryWithEncoding(data, xPathOrCSS, encoding); 121 | } 122 | 123 | NSMutableArray * hppleElements = [NSMutableArray array]; 124 | for (id node in detailNodes) { 125 | [hppleElements addObject:[TFHppleElement hppleElementWithNode:node isXML:isXML withEncoding:encoding]]; 126 | } 127 | return hppleElements; 128 | } 129 | 130 | // Returns first element at xPath 131 | - (TFHppleElement *) peekAtSearchWithXPathQuery:(NSString *)xPathOrCSS 132 | { 133 | NSArray * elements = [self searchWithXPathQuery:xPathOrCSS]; 134 | if ([elements count] >= 1) { 135 | return [elements objectAtIndex:0]; 136 | } 137 | 138 | return nil; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/Hpple/TFHppleElement.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFHppleElement.h 3 | // Hpple 4 | // 5 | // Created by Geoffrey Grosenbach on 1/31/09. 6 | // 7 | // Copyright (c) 2009 Topfunky Corporation, http://topfunky.com 8 | // 9 | // MIT LICENSE 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | #import 31 | 32 | 33 | @interface TFHppleElement : NSObject 34 | 35 | - (id) initWithNode:(NSDictionary *) theNode isXML:(BOOL)isDataXML withEncoding:(NSString *)theEncoding; 36 | 37 | + (TFHppleElement *) hppleElementWithNode:(NSDictionary *) theNode isXML:(BOOL)isDataXML withEncoding:(NSString *)theEncoding; 38 | 39 | @property (nonatomic, copy, readonly) NSString *raw; 40 | // Returns this tag's innerHTML content. 41 | @property (nonatomic, copy, readonly) NSString *content; 42 | 43 | // Returns the name of the current tag, such as "h3". 44 | @property (nonatomic, copy, readonly) NSString *tagName; 45 | 46 | // Returns tag attributes with name as key and content as value. 47 | // href = 'http://peepcode.com' 48 | // class = 'highlight' 49 | @property (nonatomic, strong, readonly) NSDictionary *attributes; 50 | 51 | // Returns the children of a given node 52 | @property (nonatomic, strong, readonly) NSArray *children; 53 | 54 | // Returns the first child of a given node 55 | @property (nonatomic, strong, readonly) TFHppleElement *firstChild; 56 | 57 | // the parent of a node 58 | @property (nonatomic, unsafe_unretained, readonly) TFHppleElement *parent; 59 | 60 | // Returns YES if the node has any child 61 | // This is more efficient than using the children property since no NSArray is constructed 62 | - (BOOL)hasChildren; 63 | 64 | // Returns YES if this is a text node 65 | - (BOOL)isTextNode; 66 | 67 | // Provides easy access to the content of a specific attribute, 68 | // such as 'href' or 'class'. 69 | - (NSString *) objectForKey:(NSString *) theKey; 70 | 71 | // Returns the children whose tag name equals the given string 72 | // (comparison is performed with NSString's isEqualToString) 73 | // Returns an empty array if no matching child is found 74 | - (NSArray *) childrenWithTagName:(NSString *)tagName; 75 | 76 | // Returns the first child node whose tag name equals the given string 77 | // (comparison is performed with NSString's isEqualToString) 78 | // Returns nil if no matching child is found 79 | - (TFHppleElement *) firstChildWithTagName:(NSString *)tagName; 80 | 81 | // Returns the children whose class equals the given string 82 | // (comparison is performed with NSString's isEqualToString) 83 | // Returns an empty array if no matching child is found 84 | - (NSArray *) childrenWithClassName:(NSString *)className; 85 | 86 | // Returns the first child whose class requals the given string 87 | // (comparison is performed with NSString's isEqualToString) 88 | // Returns nil if no matching child is found 89 | - (TFHppleElement *) firstChildWithClassName:(NSString*)className; 90 | 91 | // Returns the first text node from this element's children 92 | // Returns nil if there is no text node among the children 93 | - (TFHppleElement *) firstTextChild; 94 | 95 | // Returns the string contained by the first text node from this element's children 96 | // Convenience method which can be used instead of firstTextChild.content 97 | - (NSString *) text; 98 | 99 | // Returns elements searched with xpath 100 | - (NSArray *) searchWithXPathQuery:(NSString *)xPathOrCSS; 101 | 102 | // Custom keyed subscripting 103 | - (id)objectForKeyedSubscript:(id)key; 104 | 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/Hpple/TFHppleElement.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFHppleElement.m 3 | // Hpple 4 | // 5 | // Created by Geoffrey Grosenbach on 1/31/09. 6 | // 7 | // Copyright (c) 2009 Topfunky Corporation, http://topfunky.com 8 | // 9 | // MIT LICENSE 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | 31 | #import "TFHppleElement.h" 32 | #import "XPathQuery.h" 33 | 34 | static NSString * const TFHppleNodeContentKey = @"nodeContent"; 35 | static NSString * const TFHppleNodeNameKey = @"nodeName"; 36 | static NSString * const TFHppleNodeChildrenKey = @"nodeChildArray"; 37 | static NSString * const TFHppleNodeAttributeArrayKey = @"nodeAttributeArray"; 38 | static NSString * const TFHppleNodeAttributeNameKey = @"attributeName"; 39 | 40 | static NSString * const TFHppleTextNodeName = @"text"; 41 | 42 | @interface TFHppleElement () 43 | { 44 | NSDictionary * node; 45 | BOOL isXML; 46 | NSString *encoding; 47 | __unsafe_unretained TFHppleElement *parent; 48 | } 49 | 50 | @property (nonatomic, unsafe_unretained, readwrite) TFHppleElement *parent; 51 | 52 | @end 53 | 54 | @implementation TFHppleElement 55 | @synthesize parent; 56 | 57 | 58 | - (id) initWithNode:(NSDictionary *) theNode isXML:(BOOL)isDataXML withEncoding:(NSString *)theEncoding 59 | { 60 | if (!(self = [super init])) 61 | return nil; 62 | 63 | isXML = isDataXML; 64 | node = theNode; 65 | encoding = theEncoding; 66 | 67 | return self; 68 | } 69 | 70 | + (TFHppleElement *) hppleElementWithNode:(NSDictionary *) theNode isXML:(BOOL)isDataXML withEncoding:(NSString *)theEncoding 71 | { 72 | return [[[self class] alloc] initWithNode:theNode isXML:isDataXML withEncoding:theEncoding]; 73 | } 74 | 75 | #pragma mark - 76 | 77 | - (NSString *)raw 78 | { 79 | return [node objectForKey:@"raw"]; 80 | } 81 | 82 | - (NSString *) content 83 | { 84 | return [node objectForKey:TFHppleNodeContentKey]; 85 | } 86 | 87 | 88 | - (NSString *) tagName 89 | { 90 | return [node objectForKey:TFHppleNodeNameKey]; 91 | } 92 | 93 | - (NSArray *) children 94 | { 95 | NSMutableArray *children = [NSMutableArray array]; 96 | for (NSDictionary *child in [node objectForKey:TFHppleNodeChildrenKey]) { 97 | TFHppleElement *element = [TFHppleElement hppleElementWithNode:child isXML:isXML withEncoding:encoding]; 98 | element.parent = self; 99 | [children addObject:element]; 100 | } 101 | return children; 102 | } 103 | 104 | - (TFHppleElement *) firstChild 105 | { 106 | NSArray * children = self.children; 107 | if (children.count) 108 | return [children objectAtIndex:0]; 109 | return nil; 110 | } 111 | 112 | 113 | - (NSDictionary *) attributes 114 | { 115 | NSMutableDictionary * translatedAttributes = [NSMutableDictionary dictionary]; 116 | for (NSDictionary * attributeDict in [node objectForKey:TFHppleNodeAttributeArrayKey]) { 117 | if ([attributeDict objectForKey:TFHppleNodeContentKey] && [attributeDict objectForKey:TFHppleNodeAttributeNameKey]) { 118 | [translatedAttributes setObject:[attributeDict objectForKey:TFHppleNodeContentKey] 119 | forKey:[attributeDict objectForKey:TFHppleNodeAttributeNameKey]]; 120 | } 121 | } 122 | return translatedAttributes; 123 | } 124 | 125 | - (NSString *) objectForKey:(NSString *) theKey 126 | { 127 | return [[self attributes] objectForKey:theKey]; 128 | } 129 | 130 | - (id) description 131 | { 132 | return [node description]; 133 | } 134 | 135 | - (BOOL)hasChildren 136 | { 137 | if ([node objectForKey:TFHppleNodeChildrenKey]) 138 | return YES; 139 | else 140 | return NO; 141 | } 142 | 143 | - (BOOL)isTextNode 144 | { 145 | // we must distinguish between real text nodes and standard nodes with tha name "text" () 146 | // real text nodes must have content 147 | if ([self.tagName isEqualToString:TFHppleTextNodeName] && (self.content)) 148 | return YES; 149 | else 150 | return NO; 151 | } 152 | 153 | - (NSArray*) childrenWithTagName:(NSString*)tagName 154 | { 155 | NSMutableArray* matches = [NSMutableArray array]; 156 | 157 | for (TFHppleElement* child in self.children) 158 | { 159 | if ([child.tagName isEqualToString:tagName]) 160 | [matches addObject:child]; 161 | } 162 | 163 | return matches; 164 | } 165 | 166 | - (TFHppleElement *) firstChildWithTagName:(NSString*)tagName 167 | { 168 | for (TFHppleElement* child in self.children) 169 | { 170 | if ([child.tagName isEqualToString:tagName]) 171 | return child; 172 | } 173 | 174 | return nil; 175 | } 176 | 177 | - (NSArray*) childrenWithClassName:(NSString*)className 178 | { 179 | NSMutableArray* matches = [NSMutableArray array]; 180 | 181 | for (TFHppleElement* child in self.children) 182 | { 183 | if ([[child objectForKey:@"class"] isEqualToString:className]) 184 | [matches addObject:child]; 185 | } 186 | 187 | return matches; 188 | } 189 | 190 | - (TFHppleElement *) firstChildWithClassName:(NSString*)className 191 | { 192 | for (TFHppleElement* child in self.children) 193 | { 194 | if ([[child objectForKey:@"class"] isEqualToString:className]) 195 | return child; 196 | } 197 | 198 | return nil; 199 | } 200 | 201 | - (TFHppleElement *) firstTextChild 202 | { 203 | for (TFHppleElement* child in self.children) 204 | { 205 | if ([child isTextNode]) 206 | return child; 207 | } 208 | 209 | return [self firstChildWithTagName:TFHppleTextNodeName]; 210 | } 211 | 212 | - (NSString *) text 213 | { 214 | return self.firstTextChild.content; 215 | } 216 | 217 | // Returns all elements at xPath. 218 | - (NSArray *) searchWithXPathQuery:(NSString *)xPathOrCSS 219 | { 220 | 221 | NSData *data = [self.raw dataUsingEncoding:NSUTF8StringEncoding]; 222 | 223 | NSArray * detailNodes = nil; 224 | if (isXML) { 225 | detailNodes = PerformXMLXPathQueryWithEncoding(data, xPathOrCSS, encoding); 226 | } else { 227 | detailNodes = PerformHTMLXPathQueryWithEncoding(data, xPathOrCSS, encoding); 228 | } 229 | 230 | NSMutableArray * hppleElements = [NSMutableArray array]; 231 | for (id newNode in detailNodes) { 232 | [hppleElements addObject:[TFHppleElement hppleElementWithNode:newNode isXML:isXML withEncoding:encoding]]; 233 | } 234 | return hppleElements; 235 | } 236 | 237 | // Custom keyed subscripting 238 | - (id)objectForKeyedSubscript:(id)key 239 | { 240 | return [self objectForKey:key]; 241 | } 242 | 243 | @end 244 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/Hpple/XPathQuery.h: -------------------------------------------------------------------------------- 1 | // 2 | // XPathQuery.h 3 | // FuelFinder 4 | // 5 | // Created by Matt Gallagher on 4/08/08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | NSArray *PerformHTMLXPathQuery(NSData *document, NSString *query); 10 | NSArray *PerformHTMLXPathQueryWithEncoding(NSData *document, NSString *query,NSString *encoding); 11 | NSArray *PerformXMLXPathQuery(NSData *document, NSString *query); 12 | NSArray *PerformXMLXPathQueryWithEncoding(NSData *document, NSString *query,NSString *encoding); 13 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/Hpple/XPathQuery.m: -------------------------------------------------------------------------------- 1 | // 2 | // XPathQuery.m 3 | // FuelFinder 4 | // 5 | // Created by Matt Gallagher on 4/08/08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "XPathQuery.h" 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | NSDictionary *DictionaryForNode(xmlNodePtr currentNode, NSMutableDictionary *parentResult,BOOL parentContent); 18 | NSArray *PerformXPathQuery(xmlDocPtr doc, NSString *query); 19 | 20 | NSDictionary *DictionaryForNode(xmlNodePtr currentNode, NSMutableDictionary *parentResult,BOOL parentContent) 21 | { 22 | NSMutableDictionary *resultForNode = [NSMutableDictionary dictionary]; 23 | 24 | if (currentNode->name) 25 | { 26 | NSString *currentNodeContent = 27 | [NSString stringWithCString:(const char *)currentNode->name encoding:NSUTF8StringEncoding]; 28 | [resultForNode setObject:currentNodeContent forKey:@"nodeName"]; 29 | } 30 | 31 | if (currentNode->content && currentNode->content != (xmlChar *)-1) 32 | { 33 | NSString *currentNodeContent = 34 | [NSString stringWithCString:(const char *)currentNode->content encoding:NSUTF8StringEncoding]; 35 | 36 | if ([[resultForNode objectForKey:@"nodeName"] isEqual:@"text"] && parentResult) 37 | { 38 | if(parentContent) 39 | { 40 | [parentResult setObject:[currentNodeContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] forKey:@"nodeContent"]; 41 | return nil; 42 | } 43 | if (currentNodeContent != nil) 44 | { 45 | [resultForNode setObject:currentNodeContent forKey:@"nodeContent"]; 46 | } 47 | // NSLog(@"content: %@",currentNodeContent); 48 | return resultForNode; 49 | 50 | } 51 | else { 52 | [resultForNode setObject:currentNodeContent forKey:@"nodeContent"]; 53 | } 54 | 55 | 56 | } 57 | 58 | xmlAttr *attribute = currentNode->properties; 59 | if (attribute) 60 | { 61 | NSMutableArray *attributeArray = [NSMutableArray array]; 62 | while (attribute) 63 | { 64 | NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary]; 65 | NSString *attributeName = 66 | [NSString stringWithCString:(const char *)attribute->name encoding:NSUTF8StringEncoding]; 67 | if (attributeName) 68 | { 69 | // NSLog(@"Attribute Name Set: %@",attributeName); 70 | [attributeDictionary setObject:attributeName forKey:@"attributeName"]; 71 | } 72 | 73 | if (attribute->children) 74 | { 75 | NSDictionary *childDictionary = DictionaryForNode(attribute->children, attributeDictionary,true); 76 | if (childDictionary) 77 | { 78 | [attributeDictionary setObject:childDictionary forKey:@"attributeContent"]; 79 | } 80 | } 81 | 82 | if ([attributeDictionary count] > 0) 83 | { 84 | [attributeArray addObject:attributeDictionary]; 85 | } 86 | attribute = attribute->next; 87 | } 88 | 89 | if ([attributeArray count] > 0) 90 | { 91 | [resultForNode setObject:attributeArray forKey:@"nodeAttributeArray"]; 92 | } 93 | } 94 | 95 | xmlNodePtr childNode = currentNode->children; 96 | if (childNode) 97 | { 98 | NSMutableArray *childContentArray = [NSMutableArray array]; 99 | while (childNode) 100 | { 101 | NSDictionary *childDictionary = DictionaryForNode(childNode, resultForNode,false); 102 | if (childDictionary) 103 | { 104 | [childContentArray addObject:childDictionary]; 105 | } 106 | childNode = childNode->next; 107 | } 108 | if ([childContentArray count] > 0) 109 | { 110 | [resultForNode setObject:childContentArray forKey:@"nodeChildArray"]; 111 | } 112 | } 113 | 114 | xmlBufferPtr buffer = xmlBufferCreate(); 115 | xmlNodeDump(buffer, currentNode->doc, currentNode, 0, 0); 116 | 117 | NSString *rawContent = [NSString stringWithCString:(const char *)buffer->content encoding:NSUTF8StringEncoding]; 118 | if (rawContent != nil) 119 | { 120 | [resultForNode setObject:rawContent forKey:@"raw"]; 121 | } 122 | xmlBufferFree(buffer); 123 | 124 | return resultForNode; 125 | } 126 | 127 | NSArray *PerformXPathQuery(xmlDocPtr doc, NSString *query) 128 | { 129 | xmlXPathContextPtr xpathCtx; 130 | xmlXPathObjectPtr xpathObj; 131 | 132 | /* Make sure that passed query is non-nil and is NSString object */ 133 | if (query == nil || ![query isKindOfClass:[NSString class]]) 134 | { 135 | return nil; 136 | } 137 | 138 | /* Create xpath evaluation context */ 139 | xpathCtx = xmlXPathNewContext(doc); 140 | if(xpathCtx == NULL) 141 | { 142 | NSLog(@"Unable to create XPath context."); 143 | return nil; 144 | } 145 | 146 | /* Evaluate xpath expression */ 147 | xpathObj = xmlXPathEvalExpression((xmlChar *)[query cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx); 148 | if(xpathObj == NULL) { 149 | NSLog(@"Unable to evaluate XPath."); 150 | xmlXPathFreeContext(xpathCtx); 151 | return nil; 152 | } 153 | 154 | xmlNodeSetPtr nodes = xpathObj->nodesetval; 155 | if (!nodes) 156 | { 157 | NSLog(@"Nodes was nil."); 158 | xmlXPathFreeObject(xpathObj); 159 | xmlXPathFreeContext(xpathCtx); 160 | return nil; 161 | } 162 | 163 | NSMutableArray *resultNodes = [NSMutableArray array]; 164 | for (NSInteger i = 0; i < nodes->nodeNr; i++) 165 | { 166 | NSDictionary *nodeDictionary = DictionaryForNode(nodes->nodeTab[i], nil,false); 167 | if (nodeDictionary) 168 | { 169 | [resultNodes addObject:nodeDictionary]; 170 | } 171 | } 172 | 173 | /* Cleanup */ 174 | xmlXPathFreeObject(xpathObj); 175 | xmlXPathFreeContext(xpathCtx); 176 | 177 | return resultNodes; 178 | } 179 | 180 | NSArray *PerformHTMLXPathQuery(NSData *document, NSString *query) 181 | { 182 | return PerformHTMLXPathQueryWithEncoding(document, query, nil); 183 | } 184 | 185 | NSArray *PerformHTMLXPathQueryWithEncoding(NSData *document, NSString *query,NSString *encoding) 186 | { 187 | xmlDocPtr doc; 188 | 189 | /* Load XML document */ 190 | const char *encoded = encoding ? [encoding cStringUsingEncoding:NSUTF8StringEncoding] : NULL; 191 | 192 | doc = htmlReadMemory([document bytes], (int)[document length], "", encoded, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR); 193 | 194 | if (doc == NULL) 195 | { 196 | NSLog(@"Unable to parse."); 197 | return nil; 198 | } 199 | 200 | NSArray *result = PerformXPathQuery(doc, query); 201 | xmlFreeDoc(doc); 202 | 203 | return result; 204 | } 205 | 206 | NSArray *PerformXMLXPathQuery(NSData *document, NSString *query) 207 | { 208 | return PerformXMLXPathQueryWithEncoding(document, query, nil); 209 | } 210 | 211 | NSArray *PerformXMLXPathQueryWithEncoding(NSData *document, NSString *query,NSString *encoding) 212 | { 213 | xmlDocPtr doc; 214 | 215 | /* Load XML document */ 216 | const char *encoded = encoding ? [encoding cStringUsingEncoding:NSUTF8StringEncoding] : NULL; 217 | 218 | doc = xmlReadMemory([document bytes], (int)[document length], "", encoded, XML_PARSE_RECOVER); 219 | 220 | if (doc == NULL) 221 | { 222 | NSLog(@"Unable to parse."); 223 | return nil; 224 | } 225 | 226 | NSArray *result = PerformXPathQuery(doc, query); 227 | xmlFreeDoc(doc); 228 | 229 | return result; 230 | } 231 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+AccessObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+AccessObject.h 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist.h" 10 | 11 | #import "LightWeightPlistObjects.h" 12 | 13 | #define lwpCache [LightWeightPlist objects].dataCache 14 | #define lwpPointerMapping [LightWeightPlist objects].pointerMapping 15 | 16 | @interface LightWeightPlist (AccessObject) 17 | 18 | + (LightWeightPlistObjects *)objects; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+AccessObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+AccessObject.m 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist+AccessObject.h" 10 | 11 | #import 12 | 13 | @implementation LightWeightPlist (AccessObject) 14 | 15 | #pragma mark - class method 16 | 17 | + (LightWeightPlistObjects *)objects 18 | { 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^{ 21 | LightWeightPlistObjects *objects = [LightWeightPlistObjects new]; 22 | [objects.dataCache setDelegate:(id )self]; 23 | objc_setAssociatedObject(self, _cmd, objects, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 24 | }); 25 | return objc_getAssociatedObject(self, _cmd); 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+FilePath.h: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+FilePath.h 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist.h" 10 | 11 | #define lwpResourceFile(fmt) [LightWeightPlist resourceFolderPathWithFilename:fmt] 12 | #define lwpDocumentFile(fmt) [LightWeightPlist documentFolderPathWithFilename:fmt] 13 | 14 | @interface LightWeightPlist (FilePath) 15 | 16 | + (NSString *)resourceFolderPathWithFilename:(NSString *)filename; 17 | + (NSString *)documentFolderPathWithFilename:(NSString *)filename; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+FilePath.m: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+FilePath.m 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist+FilePath.h" 10 | 11 | #import "LightWeightPlist+AccessObject.h" 12 | 13 | @implementation LightWeightPlist (FilePath) 14 | 15 | #pragma mark - class method 16 | 17 | + (NSString *)resourceFolderPathWithFilename:(NSString *)filename 18 | { 19 | return [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", filename]]; 20 | } 21 | 22 | + (NSString *)documentFolderPathWithFilename:(NSString *)filename 23 | { 24 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 25 | NSString *documentsDirectory = [paths objectAtIndex:0]; 26 | return [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", filename]]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+HandleCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+HandleCache.h 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/20. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist.h" 10 | 11 | @interface LightWeightPlist (HandleCache) 12 | 13 | + (BOOL)setObjectToCache:(id)object withKey:(NSString *)key; 14 | + (id)objectFromCache:(NSString *)key; 15 | + (void)removeObjectFromCache:(NSString *)key; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+HandleCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+HandleCache.m 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/20. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist+HandleCache.h" 10 | 11 | #import 12 | 13 | #import "LightWeightPlist+AccessObject.h" 14 | #import "LightWeightPlist+FilePath.h" 15 | 16 | #define lwpBridge(fmt) ((__bridge const void *)fmt) 17 | 18 | @implementation LightWeightPlist (HandleCache) 19 | 20 | #pragma mark - NSCacheDelegate 21 | 22 | + (void)cache:(NSCache *)cache willEvictObject:(id)obj { 23 | if ([lwpPointerMapping objectForKey:[self objectAddressString:obj]]) { 24 | id associatedObject = objc_getAssociatedObject(self, lwpBridge(obj)); 25 | NSString *filename = [lwpPointerMapping objectForKey:[self objectAddressString:obj]]; 26 | NSString *path = lwpDocumentFile(filename); 27 | [associatedObject performSelector:@selector(writeToFile:atomically:) withObject:path withObject:@YES]; 28 | [lwpPointerMapping removeObjectForKey:[self objectAddressString:obj]]; 29 | } 30 | } 31 | 32 | #pragma mark - class method 33 | 34 | + (BOOL)setObjectToCache:(id)object withKey:(NSString *)key 35 | { 36 | if ([self isDictionary:object] || [self isArray:object]) { 37 | NSObject *emptyObject = [NSObject new]; 38 | [lwpCache setObject:emptyObject forKey:key]; 39 | objc_setAssociatedObject(self, lwpBridge([lwpCache objectForKey:key]), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 40 | [lwpPointerMapping setObject:key forKey:[self objectAddressString:[lwpCache objectForKey:key]]]; 41 | return YES; 42 | } else { 43 | return NO; 44 | } 45 | } 46 | 47 | + (id)objectFromCache:(NSString *)key 48 | { 49 | return objc_getAssociatedObject(self, lwpBridge([lwpCache objectForKey:key])); 50 | } 51 | 52 | + (void)removeObjectFromCache:(NSString *)key 53 | { 54 | if ([lwpCache objectForKey:key]) { 55 | [lwpPointerMapping removeObjectForKey:[self objectAddressString:[lwpCache objectForKey:key]]]; 56 | [lwpCache removeObjectForKey:key]; 57 | } 58 | } 59 | 60 | #pragma mark - private 61 | 62 | + (NSString *)objectAddressString:(NSObject *)object 63 | { 64 | return [NSString stringWithFormat:@"%p", object]; 65 | } 66 | 67 | + (BOOL)isArray:(id)object 68 | { 69 | return (0 == strcmp(object_getClassName(object), "__NSArrayM") || 0 == strcmp(object_getClassName(object), "__NSCFArray")); 70 | } 71 | 72 | + (BOOL)isDictionary:(id)object 73 | { 74 | return (0 == strcmp(object_getClassName(object), "__NSDictionaryM") || 0 == strcmp(object_getClassName(object), "__NSCFDictionary")); 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+SourceFromDisk.h: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+SourceFromDisk.h 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/20. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist.h" 10 | 11 | @interface LightWeightPlist (SourceFromDisk) 12 | 13 | + (NSMutableArray *)arrayInDocument:(NSString *)key; 14 | + (NSMutableArray *)arrayInResource:(NSString *)key; 15 | + (NSMutableDictionary *)dictionaryInDocument:(NSString *)key; 16 | + (NSMutableDictionary *)dictionaryInResource:(NSString *)key; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist+SourceFromDisk.m: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist+SourceFromDisk.m 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/20. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist+SourceFromDisk.h" 10 | 11 | #import "LightWeightPlist+AccessObject.h" 12 | #import "LightWeightPlist+FilePath.h" 13 | 14 | @implementation LightWeightPlist (SourceFromDisk) 15 | 16 | #pragma mark - class method 17 | 18 | + (NSMutableArray *)arrayInDocument:(NSString *)key 19 | { 20 | return [self getPlistFile:key isArray:YES inResource:NO]; 21 | } 22 | 23 | + (NSMutableArray *)arrayInResource:(NSString *)key 24 | { 25 | return [self getPlistFile:key isArray:YES inResource:YES]; 26 | } 27 | 28 | + (NSMutableDictionary *)dictionaryInDocument:(NSString *)key 29 | { 30 | return [self getPlistFile:key isArray:NO inResource:NO]; 31 | } 32 | 33 | + (NSMutableDictionary *)dictionaryInResource:(NSString *)key 34 | { 35 | return [self getPlistFile:key isArray:NO inResource:YES]; 36 | } 37 | 38 | #pragma mark - private 39 | 40 | + (id)getPlistFile:(NSString *)filename isArray:(BOOL)isArray inResource:(BOOL)inResource 41 | { 42 | NSString *path; 43 | 44 | if (inResource) { 45 | path = lwpResourceFile(filename); 46 | } else { 47 | path = lwpDocumentFile(filename); 48 | } 49 | 50 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { 51 | return nil; 52 | } else { 53 | if (isArray) { 54 | return [NSMutableArray arrayWithContentsOfFile:path]; 55 | } else { 56 | return [NSMutableDictionary dictionaryWithContentsOfFile:path]; 57 | } 58 | } 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist.h: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist.h 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define LWPArray(fmt) [LightWeightPlist lwpArray:fmt] 12 | #define LWPArrayR(fmt) [LightWeightPlist lwpArrayFromResource:fmt] 13 | #define LWPDictionary(fmt) [LightWeightPlist lwpDictionary:fmt] 14 | #define LWPDictionaryR(fmt) [LightWeightPlist lwpArrayFromResource:fmt] 15 | #define LWPDelete(fmt) [LightWeightPlist lwpDelete:fmt] 16 | #define LWPForceWrite() [LightWeightPlist lwpForceWrite] 17 | 18 | @interface LightWeightPlist : NSObject 19 | 20 | #pragma mark - Common 21 | 22 | + (void)lwpDelete:(NSString *)key; 23 | + (void)lwpForceWrite; 24 | 25 | #pragma mark - Array 26 | 27 | + (NSMutableArray *)lwpArray:(NSString *)key; 28 | + (NSMutableArray *)lwpArrayFromResource:(NSString *)key; 29 | 30 | #pragma mark - Dictionary 31 | 32 | + (NSMutableDictionary *)lwpDictionary:(NSString *)key; 33 | + (NSMutableDictionary *)lwpDictionaryFromResource:(NSString *)key; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlist.m: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlist.m 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/3/4. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlist.h" 10 | 11 | #import "LightWeightPlist+AccessObject.h" 12 | #import "LightWeightPlist+HandleCache.h" 13 | #import "LightWeightPlist+SourceFromDisk.h" 14 | #import "LightWeightPlist+FilePath.h" 15 | 16 | @implementation LightWeightPlist 17 | 18 | #pragma mark - common 19 | 20 | + (void)lwpDelete:(NSString *)key 21 | { 22 | [[NSFileManager defaultManager] removeItemAtPath:lwpDocumentFile(key) error:NULL]; 23 | [self removeObjectFromCache:key]; 24 | } 25 | 26 | + (void)lwpForceWrite 27 | { 28 | [lwpCache removeAllObjects]; 29 | } 30 | 31 | #pragma mark - array 32 | 33 | + (NSMutableArray *)lwpArray:(NSString *)key 34 | { 35 | if (![self objectFromCache:key]) { 36 | NSMutableArray *returnObject; 37 | returnObject = [self arrayInDocument:key]; 38 | if (!returnObject) { 39 | returnObject = [self arrayInResource:key]; 40 | if (!returnObject) { 41 | returnObject = [NSMutableArray array]; 42 | } 43 | } 44 | [self setObjectToCache:returnObject withKey:key]; 45 | } 46 | return [self objectFromCache:key]; 47 | } 48 | 49 | + (NSMutableArray *)lwpArrayFromResource:(NSString *)key 50 | { 51 | if (![self objectFromCache:key]) { 52 | NSMutableArray *returnObject; 53 | returnObject = [self arrayInResource:key]; 54 | if (!returnObject) { 55 | returnObject = [NSMutableArray array]; 56 | } 57 | [self setObjectToCache:returnObject withKey:key]; 58 | } 59 | return [self objectFromCache:key]; 60 | } 61 | 62 | #pragma mark - dictionary 63 | 64 | + (NSMutableDictionary *)lwpDictionary:(NSString *)key 65 | { 66 | if (![self objectFromCache:key]) { 67 | NSMutableDictionary *returnObject; 68 | returnObject = [self dictionaryInDocument:key]; 69 | if (!returnObject) { 70 | returnObject = [self dictionaryInResource:key]; 71 | if (!returnObject) { 72 | returnObject = [NSMutableDictionary dictionary]; 73 | } 74 | } 75 | [self setObjectToCache:returnObject withKey:key]; 76 | } 77 | return [self objectFromCache:key]; 78 | } 79 | 80 | + (NSMutableDictionary *)lwpDictionaryFromResource:(NSString *)key 81 | { 82 | if (![self objectFromCache:key]) { 83 | NSMutableDictionary *returnObject; 84 | returnObject = [self dictionaryInResource:key]; 85 | if (!returnObject) { 86 | returnObject = [NSMutableDictionary dictionary]; 87 | } 88 | [self setObjectToCache:returnObject withKey:key]; 89 | } 90 | return [self objectFromCache:key]; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlistObjects.h: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlistObjects.h 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/6/10. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LightWeightPlistObjects : NSObject 12 | 13 | @property (nonatomic, strong) NSCache *dataCache; 14 | @property (nonatomic, strong) NSMutableDictionary *pointerMapping; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/LightWeightPlist/LightWeightPlistObjects.m: -------------------------------------------------------------------------------- 1 | // 2 | // LightWeightPlistObjects.m 3 | // LightWeightPlist 4 | // 5 | // Created by 啟倫 陳 on 2014/6/10. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import "LightWeightPlistObjects.h" 10 | 11 | @implementation LightWeightPlistObjects 12 | 13 | #pragma mark - life cycle 14 | 15 | - (id)init 16 | { 17 | self = [super init]; 18 | if (self) { 19 | self.dataCache = [NSCache new]; 20 | self.pointerMapping = [NSMutableDictionary dictionary]; 21 | } 22 | return self; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/MKAnnotationView+WebCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // MKAnnotationView+WebCache.h 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 14/03/12. 6 | // Copyright (c) 2012 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "MapKit/MapKit.h" 10 | #import "SDWebImageManager.h" 11 | 12 | /** 13 | * Integrates SDWebImage async downloading and caching of remote images with MKAnnotationView. 14 | */ 15 | @interface MKAnnotationView (WebCache) 16 | 17 | /** 18 | * Get the current image URL. 19 | * 20 | * Note that because of the limitations of categories this property can get out of sync 21 | * if you use sd_setImage: directly. 22 | */ 23 | - (NSURL *)sd_imageURL; 24 | 25 | /** 26 | * Set the imageView `image` with an `url`. 27 | * 28 | * The download is asynchronous and cached. 29 | * 30 | * @param url The url for the image. 31 | */ 32 | - (void)sd_setImageWithURL:(NSURL *)url; 33 | 34 | /** 35 | * Set the imageView `image` with an `url` and a placeholder. 36 | * 37 | * The download is asynchronous and cached. 38 | * 39 | * @param url The url for the image. 40 | * @param placeholder The image to be set initially, until the image request finishes. 41 | * @see sd_setImageWithURL:placeholderImage:options: 42 | */ 43 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; 44 | 45 | /** 46 | * Set the imageView `image` with an `url`, placeholder and custom options. 47 | * 48 | * The download is asynchronous and cached. 49 | * 50 | * @param url The url for the image. 51 | * @param placeholder The image to be set initially, until the image request finishes. 52 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 53 | */ 54 | 55 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options; 56 | 57 | /** 58 | * Set the imageView `image` with an `url`. 59 | * 60 | * The download is asynchronous and cached. 61 | * 62 | * @param url The url for the image. 63 | * @param completedBlock A block called when operation has been completed. This block has no return value 64 | * and takes the requested UIImage as first parameter. In case of error the image parameter 65 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 66 | * indicating if the image was retrived from the local cache or from the network. 67 | * The forth parameter is the original image url. 68 | */ 69 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; 70 | 71 | /** 72 | * Set the imageView `image` with an `url`, placeholder. 73 | * 74 | * The download is asynchronous and cached. 75 | * 76 | * @param url The url for the image. 77 | * @param placeholder The image to be set initially, until the image request finishes. 78 | * @param completedBlock A block called when operation has been completed. This block has no return value 79 | * and takes the requested UIImage as first parameter. In case of error the image parameter 80 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 81 | * indicating if the image was retrived from the local cache or from the network. 82 | * The forth parameter is the original image url. 83 | */ 84 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; 85 | 86 | /** 87 | * Set the imageView `image` with an `url`, placeholder and custom options. 88 | * 89 | * The download is asynchronous and cached. 90 | * 91 | * @param url The url for the image. 92 | * @param placeholder The image to be set initially, until the image request finishes. 93 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 94 | * @param completedBlock A block called when operation has been completed. This block has no return value 95 | * and takes the requested UIImage as first parameter. In case of error the image parameter 96 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 97 | * indicating if the image was retrived from the local cache or from the network. 98 | * The forth parameter is the original image url. 99 | */ 100 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; 101 | 102 | /** 103 | * Cancel the current download 104 | */ 105 | - (void)sd_cancelCurrentImageLoad; 106 | 107 | @end 108 | 109 | 110 | @interface MKAnnotationView (WebCacheDeprecated) 111 | 112 | - (NSURL *)imageURL __deprecated_msg("Use `sd_imageURL`"); 113 | 114 | - (void)setImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`"); 115 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`"); 116 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:`"); 117 | 118 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`"); 119 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`"); 120 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`"); 121 | 122 | - (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelCurrentImageLoad`"); 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/MKAnnotationView+WebCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKAnnotationView+WebCache.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 14/03/12. 6 | // Copyright (c) 2012 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "MKAnnotationView+WebCache.h" 10 | #import "objc/runtime.h" 11 | #import "UIView+WebCacheOperation.h" 12 | 13 | static char imageURLKey; 14 | 15 | @implementation MKAnnotationView (WebCache) 16 | 17 | - (NSURL *)sd_imageURL { 18 | return objc_getAssociatedObject(self, &imageURLKey); 19 | } 20 | 21 | - (void)sd_setImageWithURL:(NSURL *)url { 22 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:nil]; 23 | } 24 | 25 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { 26 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:nil]; 27 | } 28 | 29 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 30 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil]; 31 | } 32 | 33 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { 34 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:completedBlock]; 35 | } 36 | 37 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { 38 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:completedBlock]; 39 | } 40 | 41 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 42 | [self sd_cancelCurrentImageLoad]; 43 | 44 | objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 45 | self.image = placeholder; 46 | 47 | if (url) { 48 | __weak MKAnnotationView *wself = self; 49 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 50 | if (!wself) return; 51 | dispatch_main_sync_safe(^{ 52 | __strong MKAnnotationView *sself = wself; 53 | if (!sself) return; 54 | if (image) { 55 | sself.image = image; 56 | } 57 | if (completedBlock && finished) { 58 | completedBlock(image, error, cacheType, url); 59 | } 60 | }); 61 | }]; 62 | [self sd_setImageLoadOperation:operation forKey:@"MKAnnotationViewImage"]; 63 | } else { 64 | dispatch_main_async_safe(^{ 65 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 66 | if (completedBlock) { 67 | completedBlock(nil, error, SDImageCacheTypeNone, url); 68 | } 69 | }); 70 | } 71 | } 72 | 73 | - (void)sd_cancelCurrentImageLoad { 74 | [self sd_cancelImageLoadOperationWithKey:@"MKAnnotationViewImage"]; 75 | } 76 | 77 | @end 78 | 79 | 80 | @implementation MKAnnotationView (WebCacheDeprecated) 81 | 82 | - (NSURL *)imageURL { 83 | return [self sd_imageURL]; 84 | } 85 | 86 | - (void)setImageWithURL:(NSURL *)url { 87 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:nil]; 88 | } 89 | 90 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { 91 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:nil]; 92 | } 93 | 94 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 95 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil]; 96 | } 97 | 98 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock { 99 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 100 | if (completedBlock) { 101 | completedBlock(image, error, cacheType); 102 | } 103 | }]; 104 | } 105 | 106 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock { 107 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 108 | if (completedBlock) { 109 | completedBlock(image, error, cacheType); 110 | } 111 | }]; 112 | } 113 | 114 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { 115 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 116 | if (completedBlock) { 117 | completedBlock(image, error, cacheType); 118 | } 119 | }]; 120 | } 121 | 122 | - (void)cancelCurrentImageLoad { 123 | [self sd_cancelCurrentImageLoad]; 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/NSData+ImageContentType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Fabrice Aneche on 06/01/14. 3 | // Copyright (c) 2014 Dailymotion. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | @interface NSData (ImageContentType) 9 | 10 | /** 11 | * Compute the content type for an image data 12 | * 13 | * @param data the input data 14 | * 15 | * @return the content type as string (i.e. image/jpeg, image/gif) 16 | */ 17 | + (NSString *)sd_contentTypeForImageData:(NSData *)data; 18 | 19 | @end 20 | 21 | 22 | @interface NSData (ImageContentTypeDeprecated) 23 | 24 | + (NSString *)contentTypeForImageData:(NSData *)data __deprecated_msg("Use `sd_contentTypeForImageData:`"); 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/NSData+ImageContentType.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Fabrice Aneche on 06/01/14. 3 | // Copyright (c) 2014 Dailymotion. All rights reserved. 4 | // 5 | 6 | #import "NSData+ImageContentType.h" 7 | 8 | 9 | @implementation NSData (ImageContentType) 10 | 11 | + (NSString *)sd_contentTypeForImageData:(NSData *)data { 12 | uint8_t c; 13 | [data getBytes:&c length:1]; 14 | switch (c) { 15 | case 0xFF: 16 | return @"image/jpeg"; 17 | case 0x89: 18 | return @"image/png"; 19 | case 0x47: 20 | return @"image/gif"; 21 | case 0x49: 22 | case 0x4D: 23 | return @"image/tiff"; 24 | case 0x52: 25 | // R as RIFF for WEBP 26 | if ([data length] < 12) { 27 | return nil; 28 | } 29 | 30 | NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding]; 31 | if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) { 32 | return @"image/webp"; 33 | } 34 | 35 | return nil; 36 | } 37 | return nil; 38 | } 39 | 40 | @end 41 | 42 | 43 | @implementation NSData (ImageContentTypeDeprecated) 44 | 45 | + (NSString *)contentTypeForImageData:(NSData *)data { 46 | return [self sd_contentTypeForImageData:data]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDImageCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageCompat.h" 11 | 12 | typedef NS_ENUM(NSInteger, SDImageCacheType) { 13 | /** 14 | * The image wasn't available the SDWebImage caches, but was downloaded from the web. 15 | */ 16 | SDImageCacheTypeNone, 17 | /** 18 | * The image was obtained from the disk cache. 19 | */ 20 | SDImageCacheTypeDisk, 21 | /** 22 | * The image was obtained from the memory cache. 23 | */ 24 | SDImageCacheTypeMemory 25 | }; 26 | 27 | typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType cacheType); 28 | 29 | typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); 30 | 31 | typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize); 32 | 33 | /** 34 | * SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed 35 | * asynchronous so it doesn’t add unnecessary latency to the UI. 36 | */ 37 | @interface SDImageCache : NSObject 38 | 39 | /** 40 | * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory. 41 | */ 42 | @property (assign, nonatomic) NSUInteger maxMemoryCost; 43 | 44 | /** 45 | * The maximum length of time to keep an image in the cache, in seconds 46 | */ 47 | @property (assign, nonatomic) NSInteger maxCacheAge; 48 | 49 | /** 50 | * The maximum size of the cache, in bytes. 51 | */ 52 | @property (assign, nonatomic) NSUInteger maxCacheSize; 53 | 54 | /** 55 | * Returns global shared cache instance 56 | * 57 | * @return SDImageCache global instance 58 | */ 59 | + (SDImageCache *)sharedImageCache; 60 | 61 | /** 62 | * Init a new cache store with a specific namespace 63 | * 64 | * @param ns The namespace to use for this cache store 65 | */ 66 | - (id)initWithNamespace:(NSString *)ns; 67 | 68 | /** 69 | * Add a read-only cache path to search for images pre-cached by SDImageCache 70 | * Useful if you want to bundle pre-loaded images with your app 71 | * 72 | * @param path The path to use for this read-only cache path 73 | */ 74 | - (void)addReadOnlyCachePath:(NSString *)path; 75 | 76 | /** 77 | * Store an image into memory and disk cache at the given key. 78 | * 79 | * @param image The image to store 80 | * @param key The unique image cache key, usually it's image absolute URL 81 | */ 82 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key; 83 | 84 | /** 85 | * Store an image into memory and optionally disk cache at the given key. 86 | * 87 | * @param image The image to store 88 | * @param key The unique image cache key, usually it's image absolute URL 89 | * @param toDisk Store the image to disk cache if YES 90 | */ 91 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk; 92 | 93 | /** 94 | * Store an image into memory and optionally disk cache at the given key. 95 | * 96 | * @param image The image to store 97 | * @param recalculate BOOL indicates if imageData can be used or a new data should be constructed from the UIImage 98 | * @param imageData The image data as returned by the server, this representation will be used for disk storage 99 | * instead of converting the given image object into a storable/compressed image format in order 100 | * to save quality and CPU 101 | * @param key The unique image cache key, usually it's image absolute URL 102 | * @param toDisk Store the image to disk cache if YES 103 | */ 104 | - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk; 105 | 106 | /** 107 | * Query the disk cache asynchronously. 108 | * 109 | * @param key The unique key used to store the wanted image 110 | */ 111 | - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock; 112 | 113 | /** 114 | * Query the memory cache synchronously. 115 | * 116 | * @param key The unique key used to store the wanted image 117 | */ 118 | - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key; 119 | 120 | /** 121 | * Query the disk cache synchronously after checking the memory cache. 122 | * 123 | * @param key The unique key used to store the wanted image 124 | */ 125 | - (UIImage *)imageFromDiskCacheForKey:(NSString *)key; 126 | 127 | /** 128 | * Remove the image from memory and disk cache synchronously 129 | * 130 | * @param key The unique image cache key 131 | */ 132 | - (void)removeImageForKey:(NSString *)key; 133 | 134 | 135 | /** 136 | * Remove the image from memory and disk cache synchronously 137 | * 138 | * @param key The unique image cache key 139 | * @param completion An block that should be executed after the image has been removed (optional) 140 | */ 141 | - (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion; 142 | 143 | /** 144 | * Remove the image from memory and optionally disk cache synchronously 145 | * 146 | * @param key The unique image cache key 147 | * @param fromDisk Also remove cache entry from disk if YES 148 | */ 149 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk; 150 | 151 | /** 152 | * Remove the image from memory and optionally disk cache synchronously 153 | * 154 | * @param key The unique image cache key 155 | * @param fromDisk Also remove cache entry from disk if YES 156 | * @param completion An block that should be executed after the image has been removed (optional) 157 | */ 158 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion; 159 | 160 | /** 161 | * Clear all memory cached images 162 | */ 163 | - (void)clearMemory; 164 | 165 | /** 166 | * Clear all disk cached images. Non-blocking method - returns immediately. 167 | * @param completion An block that should be executed after cache expiration completes (optional) 168 | */ 169 | - (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion; 170 | 171 | /** 172 | * Clear all disk cached images 173 | * @see clearDiskOnCompletion: 174 | */ 175 | - (void)clearDisk; 176 | 177 | /** 178 | * Remove all expired cached image from disk. Non-blocking method - returns immediately. 179 | * @param completionBlock An block that should be executed after cache expiration completes (optional) 180 | */ 181 | - (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock; 182 | 183 | /** 184 | * Remove all expired cached image from disk 185 | * @see cleanDiskWithCompletionBlock: 186 | */ 187 | - (void)cleanDisk; 188 | 189 | /** 190 | * Get the size used by the disk cache 191 | */ 192 | - (NSUInteger)getSize; 193 | 194 | /** 195 | * Get the number of images in the disk cache 196 | */ 197 | - (NSUInteger)getDiskCount; 198 | 199 | /** 200 | * Asynchronously calculate the disk cache's size. 201 | */ 202 | - (void)calculateSizeWithCompletionBlock:(SDWebImageCalculateSizeBlock)completionBlock; 203 | 204 | /** 205 | * Async check if image exists in disk cache already (does not load the image) 206 | * 207 | * @param key the key describing the url 208 | * @param completionBlock the block to be executed when the check is done. 209 | * @note the completion block will be always executed on the main queue 210 | */ 211 | - (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; 212 | 213 | /** 214 | * Check if image exists in disk cache already (does not load the image) 215 | * 216 | * @param key the key describing the url 217 | * 218 | * @return YES if an image exists for the given key 219 | */ 220 | - (BOOL)diskImageExistsWithKey:(NSString *)key; 221 | 222 | /** 223 | * Get the cache path for a certain key (needs the cache path root folder) 224 | * 225 | * @param key the key (can be obtained from url using cacheKeyForURL) 226 | * @param path the cach path root folder 227 | * 228 | * @return the cache path 229 | */ 230 | - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path; 231 | 232 | /** 233 | * Get the default cache path for a certain key 234 | * 235 | * @param key the key (can be obtained from url using cacheKeyForURL) 236 | * 237 | * @return the default cache path 238 | */ 239 | - (NSString *)defaultCachePathForKey:(NSString *)key; 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImageCompat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Jamie Pinkham 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import 11 | 12 | #ifdef __OBJC_GC__ 13 | #error SDWebImage does not support Objective-C Garbage Collection 14 | #endif 15 | 16 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0 17 | #error SDWebImage doesn't support Deployement Target version < 5.0 18 | #endif 19 | 20 | #if !TARGET_OS_IPHONE 21 | #import 22 | #ifndef UIImage 23 | #define UIImage NSImage 24 | #endif 25 | #ifndef UIImageView 26 | #define UIImageView NSImageView 27 | #endif 28 | #else 29 | 30 | #import 31 | 32 | #endif 33 | 34 | #ifndef NS_ENUM 35 | #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type 36 | #endif 37 | 38 | #ifndef NS_OPTIONS 39 | #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type 40 | #endif 41 | 42 | #if OS_OBJECT_USE_OBJC 43 | #undef SDDispatchQueueRelease 44 | #undef SDDispatchQueueSetterSementics 45 | #define SDDispatchQueueRelease(q) 46 | #define SDDispatchQueueSetterSementics strong 47 | #else 48 | #undef SDDispatchQueueRelease 49 | #undef SDDispatchQueueSetterSementics 50 | #define SDDispatchQueueRelease(q) (dispatch_release(q)) 51 | #define SDDispatchQueueSetterSementics assign 52 | #endif 53 | 54 | extern UIImage *SDScaledImageForKey(NSString *key, UIImage *image); 55 | 56 | typedef void(^SDWebImageNoParamsBlock)(); 57 | 58 | #define dispatch_main_sync_safe(block)\ 59 | if ([NSThread isMainThread]) {\ 60 | block();\ 61 | } else {\ 62 | dispatch_sync(dispatch_get_main_queue(), block);\ 63 | } 64 | 65 | #define dispatch_main_async_safe(block)\ 66 | if ([NSThread isMainThread]) {\ 67 | block();\ 68 | } else {\ 69 | dispatch_async(dispatch_get_main_queue(), block);\ 70 | } 71 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImageCompat.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDWebImageCompat.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 11/12/12. 6 | // Copyright (c) 2012 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "SDWebImageCompat.h" 10 | 11 | #if !__has_feature(objc_arc) 12 | #error SDWebImage is ARC only. Either turn on ARC for the project or use -fobjc-arc flag 13 | #endif 14 | 15 | inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image) { 16 | if (!image) { 17 | return nil; 18 | } 19 | 20 | if ([image.images count] > 0) { 21 | NSMutableArray *scaledImages = [NSMutableArray array]; 22 | 23 | for (UIImage *tempImage in image.images) { 24 | [scaledImages addObject:SDScaledImageForKey(key, tempImage)]; 25 | } 26 | 27 | return [UIImage animatedImageWithImages:scaledImages duration:image.duration]; 28 | } 29 | else { 30 | if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { 31 | CGFloat scale = 1.0; 32 | if (key.length >= 8) { 33 | // Search @2x. at the end of the string, before a 3 to 4 extension length (only if key len is 8 or more @2x. + 4 len ext) 34 | NSRange range = [key rangeOfString:@"@2x." options:0 range:NSMakeRange(key.length - 8, 5)]; 35 | if (range.location != NSNotFound) { 36 | scale = 2.0; 37 | } 38 | } 39 | 40 | UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; 41 | image = scaledImage; 42 | } 43 | return image; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImageDecoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * Created by james on 9/28/11. 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | #import 12 | #import "SDWebImageCompat.h" 13 | 14 | @interface UIImage (ForceDecode) 15 | 16 | + (UIImage *)decodedImageWithImage:(UIImage *)image; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImageDecoder.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * Created by james on 9/28/11. 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | #import "SDWebImageDecoder.h" 12 | 13 | @implementation UIImage (ForceDecode) 14 | 15 | + (UIImage *)decodedImageWithImage:(UIImage *)image { 16 | if (image.images) { 17 | // Do not decode animated images 18 | return image; 19 | } 20 | 21 | CGImageRef imageRef = image.CGImage; 22 | CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); 23 | CGRect imageRect = (CGRect){.origin = CGPointZero, .size = imageSize}; 24 | 25 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 26 | CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef); 27 | 28 | int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask); 29 | BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone || 30 | infoMask == kCGImageAlphaNoneSkipFirst || 31 | infoMask == kCGImageAlphaNoneSkipLast); 32 | 33 | // CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB. 34 | // https://developer.apple.com/library/mac/#qa/qa1037/_index.html 35 | if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) { 36 | // Unset the old alpha info. 37 | bitmapInfo &= ~kCGBitmapAlphaInfoMask; 38 | 39 | // Set noneSkipFirst. 40 | bitmapInfo |= kCGImageAlphaNoneSkipFirst; 41 | } 42 | // Some PNGs tell us they have alpha but only 3 components. Odd. 43 | else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) { 44 | // Unset the old alpha info. 45 | bitmapInfo &= ~kCGBitmapAlphaInfoMask; 46 | bitmapInfo |= kCGImageAlphaPremultipliedFirst; 47 | } 48 | 49 | // It calculates the bytes-per-row based on the bitsPerComponent and width arguments. 50 | CGContextRef context = CGBitmapContextCreate(NULL, 51 | imageSize.width, 52 | imageSize.height, 53 | CGImageGetBitsPerComponent(imageRef), 54 | 0, 55 | colorSpace, 56 | bitmapInfo); 57 | CGColorSpaceRelease(colorSpace); 58 | 59 | // If failed, return undecompressed image 60 | if (!context) return image; 61 | 62 | CGContextDrawImage(context, imageRect, imageRef); 63 | CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context); 64 | 65 | CGContextRelease(context); 66 | 67 | UIImage *decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation]; 68 | CGImageRelease(decompressedImageRef); 69 | return decompressedImage; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImageDownloader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageCompat.h" 11 | #import "SDWebImageOperation.h" 12 | 13 | typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) { 14 | SDWebImageDownloaderLowPriority = 1 << 0, 15 | SDWebImageDownloaderProgressiveDownload = 1 << 1, 16 | 17 | /** 18 | * By default, request prevent the of NSURLCache. With this flag, NSURLCache 19 | * is used with default policies. 20 | */ 21 | SDWebImageDownloaderUseNSURLCache = 1 << 2, 22 | 23 | /** 24 | * Call completion block with nil image/imageData if the image was read from NSURLCache 25 | * (to be combined with `SDWebImageDownloaderUseNSURLCache`). 26 | */ 27 | 28 | SDWebImageDownloaderIgnoreCachedResponse = 1 << 3, 29 | /** 30 | * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for 31 | * extra time in background to let the request finish. If the background task expires the operation will be cancelled. 32 | */ 33 | 34 | SDWebImageDownloaderContinueInBackground = 1 << 4, 35 | 36 | /** 37 | * Handles cookies stored in NSHTTPCookieStore by setting 38 | * NSMutableURLRequest.HTTPShouldHandleCookies = YES; 39 | */ 40 | SDWebImageDownloaderHandleCookies = 1 << 5, 41 | 42 | /** 43 | * Enable to allow untrusted SSL ceriticates. 44 | * Useful for testing purposes. Use with caution in production. 45 | */ 46 | SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6, 47 | 48 | /** 49 | * Put the image in the high priority queue. 50 | */ 51 | SDWebImageDownloaderHighPriority = 1 << 7, 52 | 53 | 54 | }; 55 | 56 | typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) { 57 | /** 58 | * Default value. All download operations will execute in queue style (first-in-first-out). 59 | */ 60 | SDWebImageDownloaderFIFOExecutionOrder, 61 | 62 | /** 63 | * All download operations will execute in stack style (last-in-first-out). 64 | */ 65 | SDWebImageDownloaderLIFOExecutionOrder 66 | }; 67 | 68 | extern NSString *const SDWebImageDownloadStartNotification; 69 | extern NSString *const SDWebImageDownloadStopNotification; 70 | 71 | typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize); 72 | 73 | typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished); 74 | 75 | typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers); 76 | 77 | /** 78 | * Asynchronous downloader dedicated and optimized for image loading. 79 | */ 80 | @interface SDWebImageDownloader : NSObject 81 | 82 | @property (assign, nonatomic) NSInteger maxConcurrentDownloads; 83 | 84 | /** 85 | * Shows the current amount of downloads that still need to be downloaded 86 | */ 87 | 88 | @property (readonly, nonatomic) NSUInteger currentDownloadCount; 89 | 90 | 91 | /** 92 | * The timeout value (in seconds) for the download operation. Default: 15.0. 93 | */ 94 | @property (assign, nonatomic) NSTimeInterval downloadTimeout; 95 | 96 | 97 | /** 98 | * Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`. 99 | */ 100 | @property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder; 101 | 102 | /** 103 | * Singleton method, returns the shared instance 104 | * 105 | * @return global shared instance of downloader class 106 | */ 107 | + (SDWebImageDownloader *)sharedDownloader; 108 | 109 | /** 110 | * Set username 111 | */ 112 | @property (strong, nonatomic) NSString *username; 113 | 114 | /** 115 | * Set password 116 | */ 117 | @property (strong, nonatomic) NSString *password; 118 | 119 | /** 120 | * Set filter to pick headers for downloading image HTTP request. 121 | * 122 | * This block will be invoked for each downloading image request, returned 123 | * NSDictionary will be used as headers in corresponding HTTP request. 124 | */ 125 | @property (nonatomic, copy) SDWebImageDownloaderHeadersFilterBlock headersFilter; 126 | 127 | /** 128 | * Set a value for a HTTP header to be appended to each download HTTP request. 129 | * 130 | * @param value The value for the header field. Use `nil` value to remove the header. 131 | * @param field The name of the header field to set. 132 | */ 133 | - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field; 134 | 135 | /** 136 | * Returns the value of the specified HTTP header field. 137 | * 138 | * @return The value associated with the header field field, or `nil` if there is no corresponding header field. 139 | */ 140 | - (NSString *)valueForHTTPHeaderField:(NSString *)field; 141 | 142 | /** 143 | * Creates a SDWebImageDownloader async downloader instance with a given URL 144 | * 145 | * The delegate will be informed when the image is finish downloaded or an error has happen. 146 | * 147 | * @see SDWebImageDownloaderDelegate 148 | * 149 | * @param url The URL to the image to download 150 | * @param options The options to be used for this download 151 | * @param progressBlock A block called repeatedly while the image is downloading 152 | * @param completedBlock A block called once the download is completed. 153 | * If the download succeeded, the image parameter is set, in case of error, 154 | * error parameter is set with the error. The last parameter is always YES 155 | * if SDWebImageDownloaderProgressiveDownload isn't use. With the 156 | * SDWebImageDownloaderProgressiveDownload option, this block is called 157 | * repeatedly with the partial image object and the finished argument set to NO 158 | * before to be called a last time with the full image and finished argument 159 | * set to YES. In case of error, the finished argument is always YES. 160 | * 161 | * @return A cancellable SDWebImageOperation 162 | */ 163 | - (id )downloadImageWithURL:(NSURL *)url 164 | options:(SDWebImageDownloaderOptions)options 165 | progress:(SDWebImageDownloaderProgressBlock)progressBlock 166 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock; 167 | 168 | /** 169 | * Sets the download queue suspension state 170 | */ 171 | - (void)setSuspended:(BOOL)suspended; 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImageDownloaderOperation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageDownloader.h" 11 | #import "SDWebImageOperation.h" 12 | 13 | @interface SDWebImageDownloaderOperation : NSOperation 14 | 15 | /** 16 | * The request used by the operation's connection. 17 | */ 18 | @property (strong, nonatomic, readonly) NSURLRequest *request; 19 | 20 | /** 21 | * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default. 22 | * 23 | * This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`. 24 | */ 25 | @property (nonatomic, assign) BOOL shouldUseCredentialStorage; 26 | 27 | /** 28 | * The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. 29 | * 30 | * This will be overridden by any shared credentials that exist for the username or password of the request URL, if present. 31 | */ 32 | @property (nonatomic, strong) NSURLCredential *credential; 33 | 34 | /** 35 | * The SDWebImageDownloaderOptions for the receiver. 36 | */ 37 | @property (assign, nonatomic, readonly) SDWebImageDownloaderOptions options; 38 | 39 | /** 40 | * Initializes a `SDWebImageDownloaderOperation` object 41 | * 42 | * @see SDWebImageDownloaderOperation 43 | * 44 | * @param request the URL request 45 | * @param options downloader options 46 | * @param progressBlock the block executed when a new chunk of data arrives. 47 | * @note the progress block is executed on a background queue 48 | * @param completedBlock the block executed when the download is done. 49 | * @note the completed block is executed on the main queue for success. If errors are found, there is a chance the block will be executed on a background queue 50 | * @param cancelBlock the block executed if the download (operation) is cancelled 51 | * 52 | * @return the initialized instance 53 | */ 54 | - (id)initWithRequest:(NSURLRequest *)request 55 | options:(SDWebImageDownloaderOptions)options 56 | progress:(SDWebImageDownloaderProgressBlock)progressBlock 57 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock 58 | cancelled:(SDWebImageNoParamsBlock)cancelBlock; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImageOperation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | @protocol SDWebImageOperation 12 | 13 | - (void)cancel; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImagePrefetcher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageManager.h" 11 | 12 | @class SDWebImagePrefetcher; 13 | 14 | @protocol SDWebImagePrefetcherDelegate 15 | 16 | @optional 17 | 18 | /** 19 | * Called when an image was prefetched. 20 | * 21 | * @param imagePrefetcher The current image prefetcher 22 | * @param imageURL The image url that was prefetched 23 | * @param finishedCount The total number of images that were prefetched (successful or not) 24 | * @param totalCount The total number of images that were to be prefetched 25 | */ 26 | - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount; 27 | 28 | /** 29 | * Called when all images are prefetched. 30 | * @param imagePrefetcher The current image prefetcher 31 | * @param totalCount The total number of images that were prefetched (whether successful or not) 32 | * @param skippedCount The total number of images that were skipped 33 | */ 34 | - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount; 35 | 36 | @end 37 | 38 | typedef void(^SDWebImagePrefetcherProgressBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls); 39 | typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls); 40 | 41 | /** 42 | * Prefetch some URLs in the cache for future use. Images are downloaded in low priority. 43 | */ 44 | @interface SDWebImagePrefetcher : NSObject 45 | 46 | /** 47 | * The web image manager 48 | */ 49 | @property (strong, nonatomic, readonly) SDWebImageManager *manager; 50 | 51 | /** 52 | * Maximum number of URLs to prefetch at the same time. Defaults to 3. 53 | */ 54 | @property (nonatomic, assign) NSUInteger maxConcurrentDownloads; 55 | 56 | /** 57 | * SDWebImageOptions for prefetcher. Defaults to SDWebImageLowPriority. 58 | */ 59 | @property (nonatomic, assign) SDWebImageOptions options; 60 | 61 | @property (weak, nonatomic) id delegate; 62 | 63 | /** 64 | * Return the global image prefetcher instance. 65 | */ 66 | + (SDWebImagePrefetcher *)sharedImagePrefetcher; 67 | 68 | /** 69 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, 70 | * currently one image is downloaded at a time, 71 | * and skips images for failed downloads and proceed to the next image in the list 72 | * 73 | * @param urls list of URLs to prefetch 74 | */ 75 | - (void)prefetchURLs:(NSArray *)urls; 76 | 77 | /** 78 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, 79 | * currently one image is downloaded at a time, 80 | * and skips images for failed downloads and proceed to the next image in the list 81 | * 82 | * @param urls list of URLs to prefetch 83 | * @param progressBlock block to be called when progress updates; 84 | * first parameter is the number of completed (successful or not) requests, 85 | * second parameter is the total number of images originally requested to be prefetched 86 | * @param completionBlock block to be called when prefetching is completed 87 | * first param is the number of completed (successful or not) requests, 88 | * second parameter is the number of skipped requests 89 | */ 90 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock; 91 | 92 | /** 93 | * Remove and cancel queued list 94 | */ 95 | - (void)cancelPrefetching; 96 | 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/SDWebImagePrefetcher.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "SDWebImagePrefetcher.h" 10 | 11 | #if !defined(DEBUG) && !defined (SD_VERBOSE) 12 | #define NSLog(...) 13 | #endif 14 | 15 | @interface SDWebImagePrefetcher () 16 | 17 | @property (strong, nonatomic) SDWebImageManager *manager; 18 | @property (strong, nonatomic) NSArray *prefetchURLs; 19 | @property (assign, nonatomic) NSUInteger requestedCount; 20 | @property (assign, nonatomic) NSUInteger skippedCount; 21 | @property (assign, nonatomic) NSUInteger finishedCount; 22 | @property (assign, nonatomic) NSTimeInterval startedTime; 23 | @property (copy, nonatomic) SDWebImagePrefetcherCompletionBlock completionBlock; 24 | @property (copy, nonatomic) SDWebImagePrefetcherProgressBlock progressBlock; 25 | 26 | @end 27 | 28 | @implementation SDWebImagePrefetcher 29 | 30 | + (SDWebImagePrefetcher *)sharedImagePrefetcher { 31 | static dispatch_once_t once; 32 | static id instance; 33 | dispatch_once(&once, ^{ 34 | instance = [self new]; 35 | }); 36 | return instance; 37 | } 38 | 39 | - (id)init { 40 | if ((self = [super init])) { 41 | _manager = [SDWebImageManager new]; 42 | _options = SDWebImageLowPriority; 43 | self.maxConcurrentDownloads = 3; 44 | } 45 | return self; 46 | } 47 | 48 | - (void)setMaxConcurrentDownloads:(NSUInteger)maxConcurrentDownloads { 49 | self.manager.imageDownloader.maxConcurrentDownloads = maxConcurrentDownloads; 50 | } 51 | 52 | - (NSUInteger)maxConcurrentDownloads { 53 | return self.manager.imageDownloader.maxConcurrentDownloads; 54 | } 55 | 56 | - (void)startPrefetchingAtIndex:(NSUInteger)index { 57 | if (index >= self.prefetchURLs.count) return; 58 | self.requestedCount++; 59 | [self.manager downloadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 60 | if (!finished) return; 61 | self.finishedCount++; 62 | 63 | if (image) { 64 | if (self.progressBlock) { 65 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]); 66 | } 67 | NSLog(@"Prefetched %@ out of %@", @(self.finishedCount), @(self.prefetchURLs.count)); 68 | } 69 | else { 70 | if (self.progressBlock) { 71 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]); 72 | } 73 | NSLog(@"Prefetched %@ out of %@ (Failed)", @(self.finishedCount), @(self.prefetchURLs.count)); 74 | 75 | // Add last failed 76 | self.skippedCount++; 77 | } 78 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didPrefetchURL:finishedCount:totalCount:)]) { 79 | [self.delegate imagePrefetcher:self 80 | didPrefetchURL:self.prefetchURLs[index] 81 | finishedCount:self.finishedCount 82 | totalCount:self.prefetchURLs.count 83 | ]; 84 | } 85 | 86 | if (self.prefetchURLs.count > self.requestedCount) { 87 | dispatch_async(dispatch_get_main_queue(), ^{ 88 | [self startPrefetchingAtIndex:self.requestedCount]; 89 | }); 90 | } 91 | else if (self.finishedCount == self.requestedCount) { 92 | [self reportStatus]; 93 | if (self.completionBlock) { 94 | self.completionBlock(self.finishedCount, self.skippedCount); 95 | self.completionBlock = nil; 96 | } 97 | } 98 | }]; 99 | } 100 | 101 | - (void)reportStatus { 102 | NSUInteger total = [self.prefetchURLs count]; 103 | NSLog(@"Finished prefetching (%@ successful, %@ skipped, timeElasped %.2f)", @(total - self.skippedCount), @(self.skippedCount), CFAbsoluteTimeGetCurrent() - self.startedTime); 104 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) { 105 | [self.delegate imagePrefetcher:self 106 | didFinishWithTotalCount:(total - self.skippedCount) 107 | skippedCount:self.skippedCount 108 | ]; 109 | } 110 | } 111 | 112 | - (void)prefetchURLs:(NSArray *)urls { 113 | [self prefetchURLs:urls progress:nil completed:nil]; 114 | } 115 | 116 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock { 117 | [self cancelPrefetching]; // Prevent duplicate prefetch request 118 | self.startedTime = CFAbsoluteTimeGetCurrent(); 119 | self.prefetchURLs = urls; 120 | self.completionBlock = completionBlock; 121 | self.progressBlock = progressBlock; 122 | 123 | // Starts prefetching from the very first image on the list with the max allowed concurrency 124 | NSUInteger listCount = self.prefetchURLs.count; 125 | for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) { 126 | [self startPrefetchingAtIndex:i]; 127 | } 128 | } 129 | 130 | - (void)cancelPrefetching { 131 | self.prefetchURLs = nil; 132 | self.skippedCount = 0; 133 | self.requestedCount = 0; 134 | self.finishedCount = 0; 135 | [self.manager cancelAll]; 136 | } 137 | 138 | @end 139 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImage+GIF.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GIF.h 3 | // LBGIFImage 4 | // 5 | // Created by Laurin Brandner on 06.01.12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (GIF) 12 | 13 | + (UIImage *)sd_animatedGIFNamed:(NSString *)name; 14 | 15 | + (UIImage *)sd_animatedGIFWithData:(NSData *)data; 16 | 17 | - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImage+GIF.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GIF.m 3 | // LBGIFImage 4 | // 5 | // Created by Laurin Brandner on 06.01.12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "UIImage+GIF.h" 10 | #import 11 | 12 | @implementation UIImage (GIF) 13 | 14 | + (UIImage *)sd_animatedGIFWithData:(NSData *)data { 15 | if (!data) { 16 | return nil; 17 | } 18 | 19 | CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); 20 | 21 | size_t count = CGImageSourceGetCount(source); 22 | 23 | UIImage *animatedImage; 24 | 25 | if (count <= 1) { 26 | animatedImage = [[UIImage alloc] initWithData:data]; 27 | } 28 | else { 29 | NSMutableArray *images = [NSMutableArray array]; 30 | 31 | NSTimeInterval duration = 0.0f; 32 | 33 | for (size_t i = 0; i < count; i++) { 34 | CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); 35 | 36 | duration += [self sd_frameDurationAtIndex:i source:source]; 37 | 38 | [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; 39 | 40 | CGImageRelease(image); 41 | } 42 | 43 | if (!duration) { 44 | duration = (1.0f / 10.0f) * count; 45 | } 46 | 47 | animatedImage = [UIImage animatedImageWithImages:images duration:duration]; 48 | } 49 | 50 | CFRelease(source); 51 | 52 | return animatedImage; 53 | } 54 | 55 | + (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { 56 | float frameDuration = 0.1f; 57 | CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil); 58 | NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties; 59 | NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary]; 60 | 61 | NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; 62 | if (delayTimeUnclampedProp) { 63 | frameDuration = [delayTimeUnclampedProp floatValue]; 64 | } 65 | else { 66 | 67 | NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime]; 68 | if (delayTimeProp) { 69 | frameDuration = [delayTimeProp floatValue]; 70 | } 71 | } 72 | 73 | // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. 74 | // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify 75 | // a duration of <= 10 ms. See and 76 | // for more information. 77 | 78 | if (frameDuration < 0.011f) { 79 | frameDuration = 0.100f; 80 | } 81 | 82 | CFRelease(cfFrameProperties); 83 | return frameDuration; 84 | } 85 | 86 | + (UIImage *)sd_animatedGIFNamed:(NSString *)name { 87 | CGFloat scale = [UIScreen mainScreen].scale; 88 | 89 | if (scale > 1.0f) { 90 | NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"]; 91 | 92 | NSData *data = [NSData dataWithContentsOfFile:retinaPath]; 93 | 94 | if (data) { 95 | return [UIImage sd_animatedGIFWithData:data]; 96 | } 97 | 98 | NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; 99 | 100 | data = [NSData dataWithContentsOfFile:path]; 101 | 102 | if (data) { 103 | return [UIImage sd_animatedGIFWithData:data]; 104 | } 105 | 106 | return [UIImage imageNamed:name]; 107 | } 108 | else { 109 | NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; 110 | 111 | NSData *data = [NSData dataWithContentsOfFile:path]; 112 | 113 | if (data) { 114 | return [UIImage sd_animatedGIFWithData:data]; 115 | } 116 | 117 | return [UIImage imageNamed:name]; 118 | } 119 | } 120 | 121 | - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size { 122 | if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) { 123 | return self; 124 | } 125 | 126 | CGSize scaledSize = size; 127 | CGPoint thumbnailPoint = CGPointZero; 128 | 129 | CGFloat widthFactor = size.width / self.size.width; 130 | CGFloat heightFactor = size.height / self.size.height; 131 | CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor; 132 | scaledSize.width = self.size.width * scaleFactor; 133 | scaledSize.height = self.size.height * scaleFactor; 134 | 135 | if (widthFactor > heightFactor) { 136 | thumbnailPoint.y = (size.height - scaledSize.height) * 0.5; 137 | } 138 | else if (widthFactor < heightFactor) { 139 | thumbnailPoint.x = (size.width - scaledSize.width) * 0.5; 140 | } 141 | 142 | NSMutableArray *scaledImages = [NSMutableArray array]; 143 | 144 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); 145 | 146 | for (UIImage *image in self.images) { 147 | [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)]; 148 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 149 | 150 | [scaledImages addObject:newImage]; 151 | } 152 | 153 | UIGraphicsEndImageContext(); 154 | 155 | return [UIImage animatedImageWithImages:scaledImages duration:self.duration]; 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImage+MultiFormat.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+MultiFormat.h 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (MultiFormat) 12 | 13 | + (UIImage *)sd_imageWithData:(NSData *)data; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImage+MultiFormat.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+MultiFormat.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "UIImage+MultiFormat.h" 10 | #import "UIImage+GIF.h" 11 | #import "NSData+ImageContentType.h" 12 | #import 13 | 14 | #ifdef SD_WEBP 15 | #import "UIImage+WebP.h" 16 | #endif 17 | 18 | @implementation UIImage (MultiFormat) 19 | 20 | + (UIImage *)sd_imageWithData:(NSData *)data { 21 | UIImage *image; 22 | NSString *imageContentType = [NSData sd_contentTypeForImageData:data]; 23 | if ([imageContentType isEqualToString:@"image/gif"]) { 24 | image = [UIImage sd_animatedGIFWithData:data]; 25 | } 26 | #ifdef SD_WEBP 27 | else if ([imageContentType isEqualToString:@"image/webp"]) 28 | { 29 | image = [UIImage sd_imageWithWebPData:data]; 30 | } 31 | #endif 32 | else { 33 | image = [[UIImage alloc] initWithData:data]; 34 | UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data]; 35 | if (orientation != UIImageOrientationUp) { 36 | image = [UIImage imageWithCGImage:image.CGImage 37 | scale:image.scale 38 | orientation:orientation]; 39 | } 40 | } 41 | 42 | 43 | return image; 44 | } 45 | 46 | 47 | +(UIImageOrientation)sd_imageOrientationFromImageData:(NSData *)imageData { 48 | UIImageOrientation result = UIImageOrientationUp; 49 | CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); 50 | if (imageSource) { 51 | CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); 52 | if (properties) { 53 | CFTypeRef val; 54 | int exifOrientation; 55 | val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation); 56 | if (val) { 57 | CFNumberGetValue(val, kCFNumberIntType, &exifOrientation); 58 | result = [self sd_exifOrientationToiOSOrientation:exifOrientation]; 59 | } // else - if it's not set it remains at up 60 | CFRelease((CFTypeRef) properties); 61 | } else { 62 | //NSLog(@"NO PROPERTIES, FAIL"); 63 | } 64 | CFRelease(imageSource); 65 | } 66 | return result; 67 | } 68 | 69 | #pragma mark EXIF orientation tag converter 70 | // Convert an EXIF image orientation to an iOS one. 71 | // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html 72 | + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation { 73 | UIImageOrientation orientation = UIImageOrientationUp; 74 | switch (exifOrientation) { 75 | case 1: 76 | orientation = UIImageOrientationUp; 77 | break; 78 | 79 | case 3: 80 | orientation = UIImageOrientationDown; 81 | break; 82 | 83 | case 8: 84 | orientation = UIImageOrientationLeft; 85 | break; 86 | 87 | case 6: 88 | orientation = UIImageOrientationRight; 89 | break; 90 | 91 | case 2: 92 | orientation = UIImageOrientationUpMirrored; 93 | break; 94 | 95 | case 4: 96 | orientation = UIImageOrientationDownMirrored; 97 | break; 98 | 99 | case 5: 100 | orientation = UIImageOrientationLeftMirrored; 101 | break; 102 | 103 | case 7: 104 | orientation = UIImageOrientationRightMirrored; 105 | break; 106 | default: 107 | break; 108 | } 109 | return orientation; 110 | } 111 | 112 | 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImage+WebP.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+WebP.h 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #ifdef SD_WEBP 10 | 11 | #import 12 | 13 | // Fix for issue #416 Undefined symbols for architecture armv7 since WebP introduction when deploying to device 14 | void WebPInitPremultiplyNEON(void); 15 | 16 | void WebPInitUpsamplersNEON(void); 17 | 18 | void VP8DspInitNEON(void); 19 | 20 | @interface UIImage (WebP) 21 | 22 | + (UIImage *)sd_imageWithWebPData:(NSData *)data; 23 | 24 | @end 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImage+WebP.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+WebP.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #ifdef SD_WEBP 10 | #import "UIImage+WebP.h" 11 | #import "webp/decode.h" 12 | 13 | // Callback for CGDataProviderRelease 14 | static void FreeImageData(void *info, const void *data, size_t size) 15 | { 16 | free((void *)data); 17 | } 18 | 19 | @implementation UIImage (WebP) 20 | 21 | + (UIImage *)sd_imageWithWebPData:(NSData *)data { 22 | WebPDecoderConfig config; 23 | if (!WebPInitDecoderConfig(&config)) { 24 | return nil; 25 | } 26 | 27 | config.output.colorspace = MODE_rgbA; 28 | config.options.use_threads = 1; 29 | 30 | // Decode the WebP image data into a RGBA value array. 31 | if (WebPDecode(data.bytes, data.length, &config) != VP8_STATUS_OK) { 32 | return nil; 33 | } 34 | 35 | int width = config.input.width; 36 | int height = config.input.height; 37 | if (config.options.use_scaling) { 38 | width = config.options.scaled_width; 39 | height = config.options.scaled_height; 40 | } 41 | 42 | // Construct a UIImage from the decoded RGBA value array. 43 | CGDataProviderRef provider = 44 | CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData); 45 | CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 46 | CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast; 47 | CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 48 | CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 49 | 50 | CGColorSpaceRelease(colorSpaceRef); 51 | CGDataProviderRelease(provider); 52 | 53 | UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; 54 | CGImageRelease(imageRef); 55 | 56 | return image; 57 | } 58 | 59 | @end 60 | 61 | #if !COCOAPODS 62 | // Functions to resolve some undefined symbols when using WebP and force_load flag 63 | void WebPInitPremultiplyNEON(void) {} 64 | void WebPInitUpsamplersNEON(void) {} 65 | void VP8DspInitNEON(void) {} 66 | #endif 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImageView+HighlightedWebCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageCompat.h" 11 | #import "SDWebImageManager.h" 12 | 13 | /** 14 | * Integrates SDWebImage async downloading and caching of remote images with UIImageView for highlighted state. 15 | */ 16 | @interface UIImageView (HighlightedWebCache) 17 | 18 | /** 19 | * Set the imageView `highlightedImage` with an `url`. 20 | * 21 | * The download is asynchronous and cached. 22 | * 23 | * @param url The url for the image. 24 | */ 25 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url; 26 | 27 | /** 28 | * Set the imageView `highlightedImage` with an `url` and custom options. 29 | * 30 | * The download is asynchronous and cached. 31 | * 32 | * @param url The url for the image. 33 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 34 | */ 35 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options; 36 | 37 | /** 38 | * Set the imageView `highlightedImage` with an `url`. 39 | * 40 | * The download is asynchronous and cached. 41 | * 42 | * @param url The url for the image. 43 | * @param completedBlock A block called when operation has been completed. This block has no return value 44 | * and takes the requested UIImage as first parameter. In case of error the image parameter 45 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 46 | * indicating if the image was retrived from the local cache or from the network. 47 | * The forth parameter is the original image url. 48 | */ 49 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; 50 | 51 | /** 52 | * Set the imageView `highlightedImage` with an `url` and custom options. 53 | * 54 | * The download is asynchronous and cached. 55 | * 56 | * @param url The url for the image. 57 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 58 | * @param completedBlock A block called when operation has been completed. This block has no return value 59 | * and takes the requested UIImage as first parameter. In case of error the image parameter 60 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 61 | * indicating if the image was retrived from the local cache or from the network. 62 | * The forth parameter is the original image url. 63 | */ 64 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; 65 | 66 | /** 67 | * Set the imageView `highlightedImage` with an `url` and custom options. 68 | * 69 | * The download is asynchronous and cached. 70 | * 71 | * @param url The url for the image. 72 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 73 | * @param progressBlock A block called while image is downloading 74 | * @param completedBlock A block called when operation has been completed. This block has no return value 75 | * and takes the requested UIImage as first parameter. In case of error the image parameter 76 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 77 | * indicating if the image was retrived from the local cache or from the network. 78 | * The forth parameter is the original image url. 79 | */ 80 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; 81 | 82 | /** 83 | * Cancel the current download 84 | */ 85 | - (void)sd_cancelCurrentHighlightedImageLoad; 86 | 87 | @end 88 | 89 | 90 | @interface UIImageView (HighlightedWebCacheDeprecated) 91 | 92 | - (void)setHighlightedImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:`"); 93 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:`"); 94 | - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:completed:`"); 95 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:completed:`"); 96 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:progress:completed:`"); 97 | 98 | - (void)cancelCurrentHighlightedImageLoad __deprecated_msg("Use `sd_cancelCurrentHighlightedImageLoad`"); 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImageView+HighlightedWebCache.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "UIImageView+HighlightedWebCache.h" 10 | #import "UIView+WebCacheOperation.h" 11 | 12 | #define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage" 13 | 14 | @implementation UIImageView (HighlightedWebCache) 15 | 16 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url { 17 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil]; 18 | } 19 | 20 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options { 21 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil]; 22 | } 23 | 24 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { 25 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:completedBlock]; 26 | } 27 | 28 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 29 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:completedBlock]; 30 | } 31 | 32 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { 33 | [self sd_cancelCurrentHighlightedImageLoad]; 34 | 35 | if (url) { 36 | __weak UIImageView *wself = self; 37 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 38 | if (!wself) return; 39 | dispatch_main_sync_safe (^ 40 | { 41 | if (!wself) return; 42 | if (image) { 43 | wself.highlightedImage = image; 44 | [wself setNeedsLayout]; 45 | } 46 | if (completedBlock && finished) { 47 | completedBlock(image, error, cacheType, url); 48 | } 49 | }); 50 | }]; 51 | [self sd_setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey]; 52 | } else { 53 | dispatch_main_async_safe(^{ 54 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 55 | if (completedBlock) { 56 | completedBlock(nil, error, SDImageCacheTypeNone, url); 57 | } 58 | }); 59 | } 60 | } 61 | 62 | - (void)sd_cancelCurrentHighlightedImageLoad { 63 | [self sd_cancelImageLoadOperationWithKey:UIImageViewHighlightedWebCacheOperationKey]; 64 | } 65 | 66 | @end 67 | 68 | 69 | @implementation UIImageView (HighlightedWebCacheDeprecated) 70 | 71 | - (void)setHighlightedImageWithURL:(NSURL *)url { 72 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil]; 73 | } 74 | 75 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options { 76 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil]; 77 | } 78 | 79 | - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock { 80 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 81 | if (completedBlock) { 82 | completedBlock(image, error, cacheType); 83 | } 84 | }]; 85 | } 86 | 87 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { 88 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 89 | if (completedBlock) { 90 | completedBlock(image, error, cacheType); 91 | } 92 | }]; 93 | } 94 | 95 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock { 96 | [self sd_setHighlightedImageWithURL:url options:0 progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 97 | if (completedBlock) { 98 | completedBlock(image, error, cacheType); 99 | } 100 | }]; 101 | } 102 | 103 | - (void)cancelCurrentHighlightedImageLoad { 104 | [self sd_cancelCurrentHighlightedImageLoad]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImageView+WebCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "SDWebImageCompat.h" 10 | #import "SDWebImageManager.h" 11 | 12 | /** 13 | * Integrates SDWebImage async downloading and caching of remote images with UIImageView. 14 | * 15 | * Usage with a UITableViewCell sub-class: 16 | * 17 | * @code 18 | 19 | #import 20 | 21 | ... 22 | 23 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 24 | { 25 | static NSString *MyIdentifier = @"MyIdentifier"; 26 | 27 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 28 | 29 | if (cell == nil) { 30 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] 31 | autorelease]; 32 | } 33 | 34 | // Here we use the provided sd_setImageWithURL: method to load the web image 35 | // Ensure you use a placeholder image otherwise cells will be initialized with no image 36 | [cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://example.com/image.jpg"] 37 | placeholderImage:[UIImage imageNamed:@"placeholder"]]; 38 | 39 | cell.textLabel.text = @"My Text"; 40 | return cell; 41 | } 42 | 43 | * @endcode 44 | */ 45 | @interface UIImageView (WebCache) 46 | 47 | /** 48 | * Get the current image URL. 49 | * 50 | * Note that because of the limitations of categories this property can get out of sync 51 | * if you use sd_setImage: directly. 52 | */ 53 | - (NSURL *)sd_imageURL; 54 | 55 | /** 56 | * Set the imageView `image` with an `url`. 57 | * 58 | * The download is asynchronous and cached. 59 | * 60 | * @param url The url for the image. 61 | */ 62 | - (void)sd_setImageWithURL:(NSURL *)url; 63 | 64 | /** 65 | * Set the imageView `image` with an `url` and a placeholder. 66 | * 67 | * The download is asynchronous and cached. 68 | * 69 | * @param url The url for the image. 70 | * @param placeholder The image to be set initially, until the image request finishes. 71 | * @see sd_setImageWithURL:placeholderImage:options: 72 | */ 73 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; 74 | 75 | /** 76 | * Set the imageView `image` with an `url`, placeholder and custom options. 77 | * 78 | * The download is asynchronous and cached. 79 | * 80 | * @param url The url for the image. 81 | * @param placeholder The image to be set initially, until the image request finishes. 82 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 83 | */ 84 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options; 85 | 86 | /** 87 | * Set the imageView `image` with an `url`. 88 | * 89 | * The download is asynchronous and cached. 90 | * 91 | * @param url The url for the image. 92 | * @param completedBlock A block called when operation has been completed. This block has no return value 93 | * and takes the requested UIImage as first parameter. In case of error the image parameter 94 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 95 | * indicating if the image was retrived from the local cache or from the network. 96 | * The forth parameter is the original image url. 97 | */ 98 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; 99 | 100 | /** 101 | * Set the imageView `image` with an `url`, placeholder. 102 | * 103 | * The download is asynchronous and cached. 104 | * 105 | * @param url The url for the image. 106 | * @param placeholder The image to be set initially, until the image request finishes. 107 | * @param completedBlock A block called when operation has been completed. This block has no return value 108 | * and takes the requested UIImage as first parameter. In case of error the image parameter 109 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 110 | * indicating if the image was retrived from the local cache or from the network. 111 | * The forth parameter is the original image url. 112 | */ 113 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; 114 | 115 | /** 116 | * Set the imageView `image` with an `url`, placeholder and custom options. 117 | * 118 | * The download is asynchronous and cached. 119 | * 120 | * @param url The url for the image. 121 | * @param placeholder The image to be set initially, until the image request finishes. 122 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 123 | * @param completedBlock A block called when operation has been completed. This block has no return value 124 | * and takes the requested UIImage as first parameter. In case of error the image parameter 125 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 126 | * indicating if the image was retrived from the local cache or from the network. 127 | * The forth parameter is the original image url. 128 | */ 129 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; 130 | 131 | /** 132 | * Set the imageView `image` with an `url`, placeholder and custom options. 133 | * 134 | * The download is asynchronous and cached. 135 | * 136 | * @param url The url for the image. 137 | * @param placeholder The image to be set initially, until the image request finishes. 138 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 139 | * @param progressBlock A block called while image is downloading 140 | * @param completedBlock A block called when operation has been completed. This block has no return value 141 | * and takes the requested UIImage as first parameter. In case of error the image parameter 142 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 143 | * indicating if the image was retrived from the local cache or from the network. 144 | * The forth parameter is the original image url. 145 | */ 146 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; 147 | 148 | /** 149 | * Set the imageView `image` with an `url` and a optionaly placeholder image. 150 | * 151 | * The download is asynchronous and cached. 152 | * 153 | * @param url The url for the image. 154 | * @param placeholder The image to be set initially, until the image request finishes. 155 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 156 | * @param progressBlock A block called while image is downloading 157 | * @param completedBlock A block called when operation has been completed. This block has no return value 158 | * and takes the requested UIImage as first parameter. In case of error the image parameter 159 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 160 | * indicating if the image was retrived from the local cache or from the network. 161 | * The forth parameter is the original image url. 162 | */ 163 | - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; 164 | 165 | /** 166 | * Download an array of images and starts them in an animation loop 167 | * 168 | * @param arrayOfURLs An array of NSURL 169 | */ 170 | - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs; 171 | 172 | /** 173 | * Cancel the current download 174 | */ 175 | - (void)sd_cancelCurrentImageLoad; 176 | 177 | - (void)sd_cancelCurrentAnimationImagesLoad; 178 | 179 | @end 180 | 181 | 182 | @interface UIImageView (WebCacheDeprecated) 183 | 184 | - (NSURL *)imageURL __deprecated_msg("Use `sd_imageURL`"); 185 | 186 | - (void)setImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`"); 187 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`"); 188 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options`"); 189 | 190 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`"); 191 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`"); 192 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`"); 193 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:progress:completed:`"); 194 | 195 | - (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs __deprecated_msg("Use `sd_setAnimationImagesWithURLs:`"); 196 | 197 | - (void)cancelCurrentArrayLoad __deprecated_msg("Use `sd_cancelCurrentAnimationImagesLoad`"); 198 | 199 | - (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelCurrentImageLoad`"); 200 | 201 | @end 202 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIImageView+WebCache.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "UIImageView+WebCache.h" 10 | #import "objc/runtime.h" 11 | #import "UIView+WebCacheOperation.h" 12 | 13 | static char imageURLKey; 14 | 15 | @implementation UIImageView (WebCache) 16 | 17 | - (void)sd_setImageWithURL:(NSURL *)url { 18 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil]; 19 | } 20 | 21 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { 22 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil]; 23 | } 24 | 25 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 26 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil]; 27 | } 28 | 29 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { 30 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock]; 31 | } 32 | 33 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { 34 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock]; 35 | } 36 | 37 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 38 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock]; 39 | } 40 | 41 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { 42 | [self sd_cancelCurrentImageLoad]; 43 | objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 44 | 45 | if (!(options & SDWebImageDelayPlaceholder)) { 46 | self.image = placeholder; 47 | } 48 | 49 | if (url) { 50 | __weak UIImageView *wself = self; 51 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 52 | if (!wself) return; 53 | dispatch_main_sync_safe(^{ 54 | if (!wself) return; 55 | if (image) { 56 | wself.image = image; 57 | [wself setNeedsLayout]; 58 | } else { 59 | if ((options & SDWebImageDelayPlaceholder)) { 60 | wself.image = placeholder; 61 | [wself setNeedsLayout]; 62 | } 63 | } 64 | if (completedBlock && finished) { 65 | completedBlock(image, error, cacheType, url); 66 | } 67 | }); 68 | }]; 69 | [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"]; 70 | } else { 71 | dispatch_main_async_safe(^{ 72 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 73 | if (completedBlock) { 74 | completedBlock(nil, error, SDImageCacheTypeNone, url); 75 | } 76 | }); 77 | } 78 | } 79 | 80 | - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { 81 | NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url]; 82 | UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key]; 83 | 84 | [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock]; 85 | } 86 | 87 | - (NSURL *)sd_imageURL { 88 | return objc_getAssociatedObject(self, &imageURLKey); 89 | } 90 | 91 | - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs { 92 | [self sd_cancelCurrentAnimationImagesLoad]; 93 | __weak UIImageView *wself = self; 94 | 95 | NSMutableArray *operationsArray = [[NSMutableArray alloc] init]; 96 | 97 | for (NSURL *logoImageURL in arrayOfURLs) { 98 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 99 | if (!wself) return; 100 | dispatch_main_sync_safe(^{ 101 | __strong UIImageView *sself = wself; 102 | [sself stopAnimating]; 103 | if (sself && image) { 104 | NSMutableArray *currentImages = [[sself animationImages] mutableCopy]; 105 | if (!currentImages) { 106 | currentImages = [[NSMutableArray alloc] init]; 107 | } 108 | [currentImages addObject:image]; 109 | 110 | sself.animationImages = currentImages; 111 | [sself setNeedsLayout]; 112 | } 113 | [sself startAnimating]; 114 | }); 115 | }]; 116 | [operationsArray addObject:operation]; 117 | } 118 | 119 | [self sd_setImageLoadOperation:[NSArray arrayWithArray:operationsArray] forKey:@"UIImageViewAnimationImages"]; 120 | } 121 | 122 | - (void)sd_cancelCurrentImageLoad { 123 | [self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"]; 124 | } 125 | 126 | - (void)sd_cancelCurrentAnimationImagesLoad { 127 | [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; 128 | } 129 | 130 | @end 131 | 132 | 133 | @implementation UIImageView (WebCacheDeprecated) 134 | 135 | - (NSURL *)imageURL { 136 | return [self sd_imageURL]; 137 | } 138 | 139 | - (void)setImageWithURL:(NSURL *)url { 140 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil]; 141 | } 142 | 143 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { 144 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil]; 145 | } 146 | 147 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 148 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil]; 149 | } 150 | 151 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock { 152 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 153 | if (completedBlock) { 154 | completedBlock(image, error, cacheType); 155 | } 156 | }]; 157 | } 158 | 159 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock { 160 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 161 | if (completedBlock) { 162 | completedBlock(image, error, cacheType); 163 | } 164 | }]; 165 | } 166 | 167 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock { 168 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 169 | if (completedBlock) { 170 | completedBlock(image, error, cacheType); 171 | } 172 | }]; 173 | } 174 | 175 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock { 176 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 177 | if (completedBlock) { 178 | completedBlock(image, error, cacheType); 179 | } 180 | }]; 181 | } 182 | 183 | - (void)cancelCurrentArrayLoad { 184 | [self sd_cancelCurrentAnimationImagesLoad]; 185 | } 186 | 187 | - (void)cancelCurrentImageLoad { 188 | [self sd_cancelCurrentImageLoad]; 189 | } 190 | 191 | - (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs { 192 | [self sd_setAnimationImagesWithURLs:arrayOfURLs]; 193 | } 194 | 195 | @end 196 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIView+WebCacheOperation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageManager.h" 11 | 12 | @interface UIView (WebCacheOperation) 13 | 14 | /** 15 | * Set the image load operation (storage in a UIView based dictionary) 16 | * 17 | * @param operation the operation 18 | * @param key key for storing the operation 19 | */ 20 | - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key; 21 | 22 | /** 23 | * Cancel all operations for the current UIView and key 24 | * 25 | * @param key key for identifying the operations 26 | */ 27 | - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key; 28 | 29 | /** 30 | * Just remove the operations corresponding to the current UIView and key without cancelling them 31 | * 32 | * @param key key for identifying the operations 33 | */ 34 | - (void)sd_removeImageLoadOperationWithKey:(NSString *)key; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SDWebImage/UIView+WebCacheOperation.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "UIView+WebCacheOperation.h" 10 | #import "objc/runtime.h" 11 | 12 | static char loadOperationKey; 13 | 14 | @implementation UIView (WebCacheOperation) 15 | 16 | - (NSMutableDictionary *)operationDictionary { 17 | NSMutableDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey); 18 | if (operations) { 19 | return operations; 20 | } 21 | operations = [NSMutableDictionary dictionary]; 22 | objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 23 | return operations; 24 | } 25 | 26 | - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key { 27 | [self sd_cancelImageLoadOperationWithKey:key]; 28 | NSMutableDictionary *operationDictionary = [self operationDictionary]; 29 | [operationDictionary setObject:operation forKey:key]; 30 | } 31 | 32 | - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key { 33 | // Cancel in progress downloader from queue 34 | NSMutableDictionary *operationDictionary = [self operationDictionary]; 35 | id operations = [operationDictionary objectForKey:key]; 36 | if (operations) { 37 | if ([operations isKindOfClass:[NSArray class]]) { 38 | for (id operation in operations) { 39 | if (operation) { 40 | [operation cancel]; 41 | } 42 | } 43 | } else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){ 44 | [(id) operations cancel]; 45 | } 46 | [operationDictionary removeObjectForKey:key]; 47 | } 48 | } 49 | 50 | - (void)sd_removeImageLoadOperationWithKey:(NSString *)key { 51 | NSMutableDictionary *operationDictionary = [self operationDictionary]; 52 | [operationDictionary removeObjectForKey:key]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SVProgressHUD' target in the 'SVProgressHUD' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2DimensionLovers/e-Hentai/36f15e7874bc06b631767f07a2c18aac1302190a/e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD.bundle/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2DimensionLovers/e-Hentai/36f15e7874bc06b631767f07a2c18aac1302190a/e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD.bundle/error@2x.png -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD.bundle/success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2DimensionLovers/e-Hentai/36f15e7874bc06b631767f07a2c18aac1302190a/e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD.bundle/success@2x.png -------------------------------------------------------------------------------- /e-Hentai/ThirdParty/SVProgressHUD/SVProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // SVProgressHUD.h 3 | // 4 | // Created by Sam Vermette on 27.03.11. 5 | // Copyright 2011 Sam Vermette. All rights reserved. 6 | // 7 | // https://github.com/samvermette/SVProgressHUD 8 | // 9 | 10 | #import 11 | #import 12 | 13 | extern NSString * const SVProgressHUDDidReceiveTouchEventNotification; 14 | extern NSString * const SVProgressHUDWillDisappearNotification; 15 | extern NSString * const SVProgressHUDDidDisappearNotification; 16 | extern NSString * const SVProgressHUDWillAppearNotification; 17 | extern NSString * const SVProgressHUDDidAppearNotification; 18 | 19 | extern NSString * const SVProgressHUDStatusUserInfoKey; 20 | 21 | enum { 22 | SVProgressHUDMaskTypeNone = 1, // allow user interactions while HUD is displayed 23 | SVProgressHUDMaskTypeClear, // don't allow 24 | SVProgressHUDMaskTypeBlack, // don't allow and dim the UI in the back of the HUD 25 | SVProgressHUDMaskTypeGradient // don't allow and dim the UI with a a-la-alert-view bg gradient 26 | }; 27 | 28 | typedef NSUInteger SVProgressHUDMaskType; 29 | 30 | @interface SVProgressHUD : UIView 31 | 32 | #pragma mark - Customization 33 | 34 | + (void)setBackgroundColor:(UIColor*)color; // default is [UIColor whiteColor] 35 | + (void)setForegroundColor:(UIColor*)color; // default is [UIColor blackColor] 36 | + (void)setRingThickness:(CGFloat)width; // default is 4 pt 37 | + (void)setFont:(UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] 38 | + (void)setSuccessImage:(UIImage*)image; // default is bundled success image from Glyphish 39 | + (void)setErrorImage:(UIImage*)image; // default is bundled error image from Glyphish 40 | 41 | #pragma mark - Show Methods 42 | 43 | + (void)show; 44 | + (void)showWithMaskType:(SVProgressHUDMaskType)maskType; 45 | + (void)showWithStatus:(NSString*)status; 46 | + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 47 | 48 | + (void)showProgress:(float)progress; 49 | + (void)showProgress:(float)progress status:(NSString*)status; 50 | + (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 51 | 52 | + (void)setStatus:(NSString*)string; // change the HUD loading status while it's showing 53 | 54 | // stops the activity indicator, shows a glyph + status, and dismisses HUD 1s later 55 | + (void)showSuccessWithStatus:(NSString*)string; 56 | + (void)showErrorWithStatus:(NSString *)string; 57 | + (void)showImage:(UIImage*)image status:(NSString*)status; // use 28x28 white pngs 58 | 59 | + (void)setOffsetFromCenter:(UIOffset)offset; 60 | + (void)resetOffsetFromCenter; 61 | 62 | + (void)popActivity; 63 | + (void)dismiss; 64 | 65 | + (BOOL)isVisible; 66 | 67 | @end 68 | 69 | 70 | @interface SVIndefiniteAnimatedView : UIView 71 | 72 | @property (nonatomic, assign) CGFloat strokeThickness; 73 | @property (nonatomic, assign) CGFloat radius; 74 | @property (nonatomic, strong) UIColor *strokeColor; 75 | 76 | @end -------------------------------------------------------------------------------- /e-Hentai/e-Hentai-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | tw.tyche.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /e-Hentai/e-Hentai-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | 17 | //from project 18 | #import "SVProgressHUD.h" 19 | #import "TFHpple.h" 20 | #import "UIImageView+WebCache.h" 21 | #import "HentaiParser.h" 22 | #import "FilesManager.h" 23 | #import "LightWeightPlist.h" 24 | #import "HentaiDownloadCenter.h" 25 | 26 | //LightWeightPlist 27 | #define HentaiCacheLibraryDictionary LWPDictionary(@"HentaiCacheLibrary") 28 | #define HentaiSaveLibraryArray LWPArray(@"HentaiSaveLibrary") 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /e-Hentai/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /e-Hentai/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // e-Hentai 4 | // 5 | // Created by 啟倫 陳 on 2014/8/27. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /e-HentaiTests/e-HentaiTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | tw.tyche.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /e-HentaiTests/e_HentaiTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // e_HentaiTests.m 3 | // e-HentaiTests 4 | // 5 | // Created by 啟倫 陳 on 2014/8/27. 6 | // Copyright (c) 2014年 ChilunChen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface e_HentaiTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation e_HentaiTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /e-HentaiTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------