├── .gitignore ├── Classes ├── FoldersViewController.h ├── FoldersViewController.m ├── HelpViewController.h ├── HelpViewController.m ├── LibraryDirectoryView.h ├── LibraryDirectoryView.m ├── LibraryDocumentsView.h ├── LibraryDocumentsView.m ├── LibraryViewController.h ├── LibraryViewController.m ├── ViewerAppDelegate.h └── ViewerAppDelegate.m ├── CoreData ├── CoreDataManager.h ├── CoreDataManager.m ├── DocumentFolder.h ├── DocumentFolder.m ├── ReaderDocument.h └── ReaderDocument.m ├── Graphics ├── AppIcon-057.png ├── AppIcon-072.png ├── AppIcon-076.png ├── AppIcon-114.png ├── AppIcon-120.png ├── AppIcon-144.png ├── AppIcon-152.png ├── AppIcon-167.png ├── AppIcon-180.png ├── AppIcon-PDF.png ├── Default-568h@2x.png ├── Folder-Large.png ├── Folder-Large@2x.png ├── Folder-Large@3x.png ├── Folder-Small.png ├── Folder-Small@2x.png ├── Folder-Small@3x.png ├── Icon-Check.png ├── Icon-Check@2x.png ├── Icon-Check@3x.png ├── Icon-Checked.png ├── Icon-Checked@2x.png ├── Icon-Checked@3x.png ├── Icon-Cross.png ├── Icon-Cross@2x.png ├── Icon-Cross@3x.png ├── Icon-Edit.png ├── Icon-Edit@2x.png ├── Icon-Edit@3x.png ├── Icon-Folder.png ├── Icon-Folder@2x.png ├── Icon-Folder@3x.png ├── Icon-Minus.png ├── Icon-Minus@2x.png ├── Icon-Minus@3x.png ├── Icon-Plus.png ├── Icon-Plus@2x.png ├── Icon-Plus@3x.png ├── Reader-Button-H.png ├── Reader-Button-H@2x.png ├── Reader-Button-H@3x.png ├── Reader-Button-N.png ├── Reader-Button-N@2x.png ├── Reader-Button-N@3x.png ├── Reader-Email.png ├── Reader-Email@2x.png ├── Reader-Email@3x.png ├── Reader-Mark-N.png ├── Reader-Mark-N@2x.png ├── Reader-Mark-N@3x.png ├── Reader-Mark-Y.png ├── Reader-Mark-Y@2x.png ├── Reader-Mark-Y@3x.png ├── Reader-Print.png ├── Reader-Print@2x.png ├── Reader-Print@3x.png ├── Reader-Thumbs.png ├── Reader-Thumbs@2x.png └── Reader-Thumbs@3x.png ├── HISTORY.md ├── LICENSE.md ├── README.md ├── Reader.xcdatamodeld ├── .xccurrentversion └── Reader.xcdatamodel │ ├── elements │ └── layout ├── Resources ├── Settings.bundle │ ├── Root.plist │ └── en.lproj │ │ └── Root.strings ├── Viewer-App.storyboard └── en.lproj │ ├── Localizable.strings │ ├── help.css │ └── help.html ├── Sources ├── CGPDFDocument.h ├── CGPDFDocument.m ├── ReaderContentPage.h ├── ReaderContentPage.m ├── ReaderContentTile.h ├── ReaderContentTile.m ├── ReaderContentView.h ├── ReaderContentView.m ├── ReaderDocumentOutline.h ├── ReaderDocumentOutline.m ├── ReaderMainPagebar.h ├── ReaderMainPagebar.m ├── ReaderMainToolbar.h ├── ReaderMainToolbar.m ├── ReaderThumbCache.h ├── ReaderThumbCache.m ├── ReaderThumbFetch.h ├── ReaderThumbFetch.m ├── ReaderThumbQueue.h ├── ReaderThumbQueue.m ├── ReaderThumbRender.h ├── ReaderThumbRender.m ├── ReaderThumbRequest.h ├── ReaderThumbRequest.m ├── ReaderThumbView.h ├── ReaderThumbView.m ├── ReaderThumbsView.h ├── ReaderThumbsView.m ├── ReaderViewController.h ├── ReaderViewController.m ├── ThumbsMainToolbar.h ├── ThumbsMainToolbar.m ├── ThumbsViewController.h ├── ThumbsViewController.m ├── UIXToolbarView.h └── UIXToolbarView.m ├── Support ├── DirectoryWatcher.h ├── DirectoryWatcher.m ├── DocumentsUpdate.h ├── DocumentsUpdate.m ├── ReaderConstants.h ├── ReaderConstants.m ├── UIXTextEntry.h └── UIXTextEntry.m ├── Todo.txt ├── Viewer-Info.plist ├── Viewer-Prefix.pch ├── Viewer.xcodeproj └── project.pbxproj └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | project.xcworkspace 3 | xcuserdata 4 | -------------------------------------------------------------------------------- /Classes/FoldersViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FoldersViewController.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | #import 28 | 29 | @class FoldersViewController; 30 | 31 | @protocol FoldersViewControllerDelegate 32 | 33 | @required // Delegate protocols 34 | 35 | - (void)dismissFoldersViewController:(FoldersViewController *)viewController; 36 | 37 | - (void)foldersViewController:(FoldersViewController *)viewController didSelectObjectID:(NSManagedObjectID *)objectID; 38 | 39 | @end 40 | 41 | @interface FoldersViewController : UIViewController 42 | 43 | @property (nonatomic, weak, readwrite) id delegate; 44 | 45 | - (void)reloadData; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Classes/FoldersViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FoldersViewController.m 3 | // Viewer v1.2.1 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderConstants.h" 27 | #import "FoldersViewController.h" 28 | #import "CoreDataManager.h" 29 | #import "DocumentFolder.h" 30 | #import "UIXToolbarView.h" 31 | 32 | @interface FoldersViewController () 33 | 34 | @end 35 | 36 | @implementation FoldersViewController 37 | { 38 | UIXToolbarView *theToolbar; 39 | 40 | UILabel *theTitleLabel; 41 | 42 | UITableView *theTableView; 43 | 44 | NSMutableArray *folders; 45 | } 46 | 47 | #pragma mark Constants 48 | 49 | #define BUTTON_Y 7.0f 50 | #define BUTTON_SPACE 8.0f 51 | #define BUTTON_HEIGHT 30.0f 52 | 53 | #define TITLE_Y 8.0f 54 | #define TITLE_HEIGHT 28.0f 55 | 56 | #define CANCEL_BUTTON_WIDTH 56.0f 57 | 58 | #define STATUS_HEIGHT 20.0f 59 | 60 | #define TOOLBAR_HEIGHT 44.0f 61 | 62 | #define MAXIMUM_TABLE_WIDTH 288.0f 63 | #define MAXIMUM_TABLE_HEIGHT 464.0f 64 | 65 | #define TABLE_CELL_HEIGHT 42.0f 66 | 67 | #pragma mark Properties 68 | 69 | @synthesize delegate; 70 | 71 | #pragma mark UIViewController methods 72 | 73 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 74 | { 75 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) 76 | { 77 | folders = [NSMutableArray new]; // Document folders list 78 | } 79 | 80 | return self; 81 | } 82 | 83 | - (void)reloadData 84 | { 85 | [folders removeAllObjects]; // Remove all document folders from list 86 | 87 | NSManagedObjectContext *mainMOC = [[CoreDataManager sharedInstance] mainManagedObjectContext]; 88 | 89 | NSArray *folderList = [DocumentFolder allInMOC:mainMOC]; // Get current folder list 90 | 91 | for (DocumentFolder *folder in folderList) // Enumerate thru current folder list 92 | { 93 | if ([folder.type integerValue] != DocumentFolderTypeRecent) [folders addObject:folder]; 94 | } 95 | 96 | if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) 97 | { 98 | CGFloat maxHeight = ((TABLE_CELL_HEIGHT * folders.count) + TOOLBAR_HEIGHT); 99 | 100 | if (maxHeight > MAXIMUM_TABLE_HEIGHT) maxHeight = MAXIMUM_TABLE_HEIGHT; // Limit height 101 | 102 | self.contentSizeForViewInPopover = CGSizeMake(MAXIMUM_TABLE_WIDTH, maxHeight); 103 | } 104 | } 105 | 106 | - (void)viewDidLoad 107 | { 108 | [super viewDidLoad]; 109 | 110 | assert(delegate != nil); // Check delegate 111 | 112 | self.view.backgroundColor = [UIColor grayColor]; // Neutral gray 113 | 114 | UIUserInterfaceIdiom userInterfaceIdiom = [UIDevice currentDevice].userInterfaceIdiom; 115 | 116 | CGRect viewRect = self.view.bounds; UIView *fakeStatusBar = nil; 117 | 118 | if (userInterfaceIdiom == UIUserInterfaceIdiomPhone) // Small device 119 | { 120 | if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) // iOS 7+ 121 | { 122 | if ([self prefersStatusBarHidden] == NO) // Visible status bar 123 | { 124 | CGRect statusBarRect = self.view.bounds; // Status bar frame 125 | statusBarRect.size.height = STATUS_HEIGHT; // Default status height 126 | fakeStatusBar = [[UIView alloc] initWithFrame:statusBarRect]; // UIView 127 | fakeStatusBar.autoresizingMask = UIViewAutoresizingFlexibleWidth; 128 | fakeStatusBar.backgroundColor = [UIColor blackColor]; 129 | fakeStatusBar.contentMode = UIViewContentModeRedraw; 130 | fakeStatusBar.userInteractionEnabled = NO; 131 | 132 | viewRect.origin.y += STATUS_HEIGHT; viewRect.size.height -= STATUS_HEIGHT; 133 | } 134 | } 135 | } 136 | 137 | CGRect toolbarRect = viewRect; toolbarRect.size.height = TOOLBAR_HEIGHT; 138 | theToolbar = [[UIXToolbarView alloc] initWithFrame:toolbarRect]; // UIXToolbarView 139 | [self.view addSubview:theToolbar]; // Add toolbar to view controller view 140 | 141 | CGFloat toolbarWidth = theToolbar.bounds.size.width; // Toolbar width 142 | 143 | CGFloat titleX = BUTTON_SPACE; CGFloat titleWidth = (toolbarWidth - (BUTTON_SPACE + BUTTON_SPACE)); 144 | 145 | if (userInterfaceIdiom == UIUserInterfaceIdiomPhone) // Small device 146 | { 147 | UIImage *imageH = [UIImage imageNamed:@"Reader-Button-H"]; 148 | UIImage *imageN = [UIImage imageNamed:@"Reader-Button-N"]; 149 | 150 | UIImage *buttonH = [imageH stretchableImageWithLeftCapWidth:5 topCapHeight:0]; 151 | UIImage *buttonN = [imageN stretchableImageWithLeftCapWidth:5 topCapHeight:0]; 152 | 153 | titleWidth -= (CANCEL_BUTTON_WIDTH + BUTTON_SPACE); // Adjust title width 154 | 155 | CGFloat rightButtonX = (toolbarWidth - (CANCEL_BUTTON_WIDTH + BUTTON_SPACE)); // X 156 | 157 | UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; // UIButton 158 | cancelButton.frame = CGRectMake(rightButtonX, BUTTON_Y, CANCEL_BUTTON_WIDTH, BUTTON_HEIGHT); 159 | [cancelButton setTitle:NSLocalizedString(@"Cancel", @"button") forState:UIControlStateNormal]; 160 | [cancelButton setTitleColor:[UIColor colorWithWhite:0.0f alpha:1.0f] forState:UIControlStateNormal]; 161 | [cancelButton setTitleColor:[UIColor colorWithWhite:1.0f alpha:1.0f] forState:UIControlStateHighlighted]; 162 | [cancelButton addTarget:self action:@selector(cancelButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 163 | [cancelButton setBackgroundImage:buttonH forState:UIControlStateHighlighted]; 164 | [cancelButton setBackgroundImage:buttonN forState:UIControlStateNormal]; 165 | cancelButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; 166 | cancelButton.titleLabel.font = [UIFont systemFontOfSize:14.0f]; 167 | cancelButton.exclusiveTouch = YES; 168 | [theToolbar addSubview:cancelButton]; // Add button to toolbar 169 | } 170 | else // Large device 171 | { 172 | self.contentSizeForViewInPopover = CGSizeMake(MAXIMUM_TABLE_WIDTH, MAXIMUM_TABLE_HEIGHT); 173 | } 174 | 175 | CGRect titleRect = CGRectMake(titleX, TITLE_Y, titleWidth, TITLE_HEIGHT); 176 | theTitleLabel = [[UILabel alloc] initWithFrame:titleRect]; // UILabel 177 | theTitleLabel.textAlignment = NSTextAlignmentCenter; 178 | theTitleLabel.font = [UIFont systemFontOfSize:19.0f]; 179 | theTitleLabel.textColor = [UIColor colorWithWhite:0.0f alpha:1.0f]; 180 | theTitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 181 | theTitleLabel.backgroundColor = [UIColor clearColor]; 182 | #if (READER_FLAT_UI == FALSE) // Option 183 | theTitleLabel.shadowColor = [UIColor colorWithWhite:0.65f alpha:1.0f]; 184 | theTitleLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); 185 | #endif // end of READER_FLAT_UI Option 186 | theTitleLabel.text = NSLocalizedString(@"Folders", @"title"); 187 | [theToolbar addSubview:theTitleLabel]; 188 | 189 | CGRect tableRect = viewRect; tableRect.origin.y += TOOLBAR_HEIGHT; tableRect.size.height -= TOOLBAR_HEIGHT; 190 | theTableView = [[UITableView alloc] initWithFrame:tableRect]; // UITableView 191 | theTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 192 | theTableView.backgroundColor = [UIColor whiteColor]; theTableView.rowHeight = TABLE_CELL_HEIGHT; 193 | theTableView.dataSource = self; theTableView.delegate = self; // UITableViewDelegate 194 | [self.view insertSubview:theTableView belowSubview:theToolbar]; 195 | 196 | if (userInterfaceIdiom == UIUserInterfaceIdiomPhone) // Small device 197 | { 198 | if (fakeStatusBar != nil) [self.view addSubview:fakeStatusBar]; // Add status bar background view 199 | } 200 | } 201 | 202 | - (void)viewWillAppear:(BOOL)animated 203 | { 204 | [super viewWillAppear:animated]; 205 | 206 | [theTableView reloadData]; // Reload table data 207 | 208 | theTableView.contentOffset = CGPointZero; 209 | } 210 | 211 | - (void)viewDidAppear:(BOOL)animated 212 | { 213 | [super viewDidAppear:animated]; 214 | 215 | [theTableView flashScrollIndicators]; 216 | } 217 | 218 | - (void)viewWillDisappear:(BOOL)animated 219 | { 220 | [super viewWillDisappear:animated]; 221 | 222 | [folders removeAllObjects]; 223 | } 224 | 225 | - (void)viewDidDisappear:(BOOL)animated 226 | { 227 | [super viewDidDisappear:animated]; 228 | } 229 | 230 | - (void)viewDidUnload 231 | { 232 | theToolbar = nil; 233 | 234 | theTitleLabel = nil; 235 | 236 | theTableView = nil; 237 | 238 | [super viewDidUnload]; 239 | } 240 | 241 | - (BOOL)prefersStatusBarHidden 242 | { 243 | return [[NSUserDefaults standardUserDefaults] boolForKey:kReaderSettingsHideStatusBar]; 244 | } 245 | 246 | - (UIStatusBarStyle)preferredStatusBarStyle 247 | { 248 | return UIStatusBarStyleLightContent; 249 | } 250 | 251 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 252 | { 253 | if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) 254 | return UIInterfaceOrientationIsPortrait(interfaceOrientation); 255 | else 256 | return YES; 257 | } 258 | 259 | /* 260 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 261 | { 262 | } 263 | 264 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration 265 | { 266 | } 267 | 268 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 269 | { 270 | //if (fromInterfaceOrientation == self.interfaceOrientation) return; 271 | } 272 | */ 273 | 274 | /* 275 | - (void)didReceiveMemoryWarning 276 | { 277 | [super didReceiveMemoryWarning]; 278 | } 279 | */ 280 | 281 | #pragma mark UITableViewDelegate methods 282 | 283 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 284 | { 285 | if ([delegate respondsToSelector:@selector(foldersViewController:didSelectObjectID:)]) 286 | { 287 | DocumentFolder *folder = [folders objectAtIndex:indexPath.row]; // Folder at row 288 | 289 | [delegate foldersViewController:self didSelectObjectID:[folder objectID]]; 290 | } 291 | } 292 | 293 | #pragma mark UITableViewDataSource methods 294 | 295 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 296 | { 297 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"tvCellFolder"]; 298 | 299 | if (cell == nil) // Create a brand new UITableViewCell for our use 300 | { 301 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"tvCellFolder"]; 302 | 303 | cell.textLabel.font = [UIFont systemFontOfSize:17.0]; cell.textLabel.textAlignment = NSTextAlignmentCenter; 304 | 305 | cell.selectionStyle = UITableViewCellSelectionStyleGray; // Use gray instead of blue 306 | } 307 | 308 | DocumentFolder *folder = [folders objectAtIndex:indexPath.row]; // Folder at row 309 | 310 | cell.textLabel.text = folder.name; 311 | 312 | return cell; 313 | } 314 | 315 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 316 | { 317 | return (folders.count); 318 | } 319 | 320 | #pragma mark UIButton action methods 321 | 322 | - (void)cancelButtonTapped:(UIButton *)button 323 | { 324 | [delegate dismissFoldersViewController:self]; 325 | } 326 | 327 | @end 328 | -------------------------------------------------------------------------------- /Classes/HelpViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HelpViewController.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @class HelpViewController; 29 | 30 | @protocol HelpViewControllerDelegate 31 | 32 | @optional // Delegate protocols 33 | 34 | - (void)dismissHelpViewController:(HelpViewController *)viewController; 35 | 36 | @end 37 | 38 | @interface HelpViewController : UIViewController 39 | 40 | @property (nonatomic, weak, readwrite) id delegate; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Classes/HelpViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HelpViewController.m 3 | // Viewer v1.2.1 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderConstants.h" 27 | #import "HelpViewController.h" 28 | #import "UIXToolbarView.h" 29 | 30 | @interface HelpViewController () 31 | 32 | @end 33 | 34 | @implementation HelpViewController 35 | { 36 | UIXToolbarView *theToolbar; 37 | 38 | UILabel *theTitleLabel; 39 | 40 | UIWebView *theWebView; 41 | 42 | BOOL htmlLoaded; 43 | } 44 | 45 | #pragma mark Constants 46 | 47 | #define BUTTON_Y 7.0f 48 | #define BUTTON_SPACE 8.0f 49 | #define BUTTON_HEIGHT 30.0f 50 | 51 | #define TITLE_Y 8.0f 52 | #define TITLE_HEIGHT 28.0f 53 | 54 | #define CLOSE_BUTTON_WIDTH 56.0f 55 | 56 | #define STATUS_HEIGHT 20.0f 57 | 58 | #define TOOLBAR_HEIGHT 44.0f 59 | 60 | #define MAXIMUM_HELP_WIDTH 512.0f 61 | #define MAXIMUM_HELP_HEIGHT 648.0f 62 | 63 | #pragma mark Properties 64 | 65 | @synthesize delegate; 66 | 67 | #pragma mark UIViewController methods 68 | 69 | /* 70 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 71 | { 72 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) 73 | { 74 | // Custom initialization 75 | } 76 | 77 | return self; 78 | } 79 | */ 80 | 81 | - (void)viewDidLoad 82 | { 83 | [super viewDidLoad]; 84 | 85 | assert(delegate != nil); // Check delegate 86 | 87 | self.view.backgroundColor = [UIColor grayColor]; // Neutral gray 88 | 89 | UIUserInterfaceIdiom userInterfaceIdiom = [UIDevice currentDevice].userInterfaceIdiom; 90 | 91 | CGRect viewRect = self.view.bounds; UIView *fakeStatusBar = nil; 92 | 93 | if (userInterfaceIdiom == UIUserInterfaceIdiomPhone) // Small device 94 | { 95 | if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) // iOS 7+ 96 | { 97 | if ([self prefersStatusBarHidden] == NO) // Visible status bar 98 | { 99 | CGRect statusBarRect = self.view.bounds; // Status bar frame 100 | statusBarRect.size.height = STATUS_HEIGHT; // Default status height 101 | fakeStatusBar = [[UIView alloc] initWithFrame:statusBarRect]; // UIView 102 | fakeStatusBar.autoresizingMask = UIViewAutoresizingFlexibleWidth; 103 | fakeStatusBar.backgroundColor = [UIColor blackColor]; 104 | fakeStatusBar.contentMode = UIViewContentModeRedraw; 105 | fakeStatusBar.userInteractionEnabled = NO; 106 | 107 | viewRect.origin.y += STATUS_HEIGHT; viewRect.size.height -= STATUS_HEIGHT; 108 | } 109 | } 110 | } 111 | 112 | CGRect toolbarRect = viewRect; toolbarRect.size.height = TOOLBAR_HEIGHT; 113 | theToolbar = [[UIXToolbarView alloc] initWithFrame:toolbarRect]; // UIXToolbarView 114 | [self.view addSubview:theToolbar]; // Add toolbar to view controller view 115 | 116 | CGFloat toolbarWidth = theToolbar.bounds.size.width; // Toolbar width 117 | 118 | CGFloat titleX = BUTTON_SPACE; CGFloat titleWidth = (toolbarWidth - (BUTTON_SPACE + BUTTON_SPACE)); 119 | 120 | if (userInterfaceIdiom == UIUserInterfaceIdiomPhone) // Small device 121 | { 122 | UIImage *imageH = [UIImage imageNamed:@"Reader-Button-H"]; 123 | UIImage *imageN = [UIImage imageNamed:@"Reader-Button-N"]; 124 | 125 | UIImage *buttonH = [imageH stretchableImageWithLeftCapWidth:5 topCapHeight:0]; 126 | UIImage *buttonN = [imageN stretchableImageWithLeftCapWidth:5 topCapHeight:0]; 127 | 128 | titleWidth -= (CLOSE_BUTTON_WIDTH + BUTTON_SPACE); // Adjust title width 129 | 130 | CGFloat rightButtonX = (toolbarWidth - (CLOSE_BUTTON_WIDTH + BUTTON_SPACE)); // X 131 | 132 | UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; // Close button 133 | closeButton.frame = CGRectMake(rightButtonX, BUTTON_Y, CLOSE_BUTTON_WIDTH, BUTTON_HEIGHT); 134 | [closeButton setTitle:NSLocalizedString(@"Close", @"button") forState:UIControlStateNormal]; 135 | [closeButton setTitleColor:[UIColor colorWithWhite:0.0f alpha:1.0f] forState:UIControlStateNormal]; 136 | [closeButton setTitleColor:[UIColor colorWithWhite:1.0f alpha:1.0f] forState:UIControlStateHighlighted]; 137 | [closeButton addTarget:self action:@selector(closeButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 138 | [closeButton setBackgroundImage:buttonH forState:UIControlStateHighlighted]; 139 | [closeButton setBackgroundImage:buttonN forState:UIControlStateNormal]; 140 | closeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; 141 | closeButton.titleLabel.font = [UIFont systemFontOfSize:14.0f]; 142 | closeButton.exclusiveTouch = YES; 143 | [theToolbar addSubview:closeButton]; // Add button to toolbar 144 | } 145 | else // Large device 146 | { 147 | self.contentSizeForViewInPopover = CGSizeMake(MAXIMUM_HELP_WIDTH, MAXIMUM_HELP_HEIGHT); 148 | } 149 | 150 | NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 151 | NSString *name = [infoDictionary objectForKey:(NSString *)kCFBundleNameKey]; 152 | NSString *version = [infoDictionary objectForKey:(NSString *)kCFBundleVersionKey]; 153 | 154 | CGRect titleRect = CGRectMake(titleX, TITLE_Y, titleWidth, TITLE_HEIGHT); 155 | theTitleLabel = [[UILabel alloc] initWithFrame:titleRect]; 156 | theTitleLabel.textAlignment = NSTextAlignmentCenter; 157 | theTitleLabel.font = [UIFont systemFontOfSize:17.0f]; 158 | theTitleLabel.textColor = [UIColor colorWithWhite:0.0f alpha:1.0f]; 159 | theTitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 160 | theTitleLabel.backgroundColor = [UIColor clearColor]; 161 | #if (READER_FLAT_UI == FALSE) // Option 162 | theTitleLabel.shadowColor = [UIColor colorWithWhite:0.65f alpha:1.0f]; 163 | theTitleLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); 164 | #endif // end of READER_FLAT_UI Option 165 | theTitleLabel.text = [NSString stringWithFormat:@"%@ v%@", name, version]; 166 | [theToolbar addSubview:theTitleLabel]; 167 | 168 | CGRect helpRect = viewRect; helpRect.origin.y += TOOLBAR_HEIGHT; helpRect.size.height -= TOOLBAR_HEIGHT; 169 | theWebView = [[UIWebView alloc] initWithFrame:helpRect]; // UIWebView 170 | theWebView.dataDetectorTypes = UIDataDetectorTypeNone; theWebView.scalesPageToFit = NO; 171 | theWebView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 172 | theWebView.delegate = self; // UIWebViewDelegate 173 | [self.view insertSubview:theWebView belowSubview:theToolbar]; 174 | 175 | if (userInterfaceIdiom == UIUserInterfaceIdiomPhone) // Small device 176 | { 177 | if (fakeStatusBar != nil) [self.view addSubview:fakeStatusBar]; // Add status bar background view 178 | } 179 | } 180 | 181 | - (void)viewWillAppear:(BOOL)animated 182 | { 183 | [super viewWillAppear:animated]; 184 | 185 | if (htmlLoaded == NO) // Load help HTML file when needed 186 | { 187 | NSString *htmlFile = [[NSBundle mainBundle] pathForResource:@"help.html" ofType:nil]; // Help HTML file 188 | 189 | NSString *htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil]; 190 | 191 | NSURL *baseURLPath = [NSURL fileURLWithPath:[htmlFile stringByDeletingLastPathComponent] isDirectory:YES]; 192 | 193 | [theWebView loadHTMLString:htmlString baseURL:baseURLPath]; htmlLoaded = YES; 194 | } 195 | } 196 | 197 | - (void)viewDidAppear:(BOOL)animated 198 | { 199 | [super viewDidAppear:animated]; 200 | } 201 | 202 | - (void)viewWillDisappear:(BOOL)animated 203 | { 204 | [super viewWillDisappear:animated]; 205 | } 206 | 207 | - (void)viewDidDisappear:(BOOL)animated 208 | { 209 | [super viewDidDisappear:animated]; 210 | } 211 | 212 | - (void)viewDidUnload 213 | { 214 | theWebView.delegate = nil; 215 | 216 | theWebView = nil; theTitleLabel = nil; theToolbar = nil; 217 | 218 | [super viewDidUnload]; htmlLoaded = NO; 219 | } 220 | 221 | - (BOOL)prefersStatusBarHidden 222 | { 223 | return [[NSUserDefaults standardUserDefaults] boolForKey:kReaderSettingsHideStatusBar]; 224 | } 225 | 226 | - (UIStatusBarStyle)preferredStatusBarStyle 227 | { 228 | return UIStatusBarStyleLightContent; 229 | } 230 | 231 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 232 | { 233 | if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) 234 | return UIInterfaceOrientationIsPortrait(interfaceOrientation); 235 | else 236 | return YES; 237 | } 238 | 239 | /* 240 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 241 | { 242 | } 243 | 244 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration 245 | { 246 | } 247 | 248 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 249 | { 250 | //if (fromInterfaceOrientation == self.interfaceOrientation) return; 251 | } 252 | */ 253 | 254 | /* 255 | - (void)didReceiveMemoryWarning 256 | { 257 | [super didReceiveMemoryWarning]; 258 | } 259 | */ 260 | 261 | - (void)dealloc 262 | { 263 | theWebView.delegate = nil; 264 | } 265 | 266 | #pragma mark UIWebViewDelegate methods 267 | 268 | /* 269 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 270 | { 271 | } 272 | */ 273 | 274 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)type 275 | { 276 | BOOL should = YES; // Default 277 | 278 | if (type == UIWebViewNavigationTypeLinkClicked) // Handle taps on links 279 | { 280 | [[UIApplication sharedApplication] openURL:[request URL]]; should = NO; 281 | } 282 | 283 | return should; 284 | } 285 | 286 | /* 287 | - (void)webViewDidFinishLoad:(UIWebView *)webView 288 | { 289 | } 290 | 291 | - (void)webViewDidStartLoad:(UIWebView *)webView 292 | { 293 | } 294 | */ 295 | 296 | #pragma mark UIButton action methods 297 | 298 | - (void)closeButtonTapped:(UIButton *)button 299 | { 300 | [delegate dismissHelpViewController:self]; 301 | } 302 | 303 | @end 304 | -------------------------------------------------------------------------------- /Classes/LibraryDirectoryView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryDirectoryView.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbsView.h" 29 | 30 | @class LibraryDirectoryView; 31 | @class DocumentFolder; 32 | @class UIXToolbarView; 33 | 34 | @protocol LibraryDirectoryDelegate 35 | 36 | @required // Delegate protocols 37 | 38 | - (void)tappedInToolbar:(UIXToolbarView *)toolbar infoButton:(UIButton *)button; 39 | 40 | - (void)directoryView:(LibraryDirectoryView *)directoryView didSelectDocumentFolder:(DocumentFolder *)folder; 41 | 42 | - (void)enableContainerScrollView:(BOOL)enabled; 43 | 44 | @end 45 | 46 | @interface LibraryDirectoryView : UIView 47 | 48 | @property (nonatomic, weak, readwrite) id delegate; 49 | 50 | @property (nonatomic, weak, readwrite) UIViewController *ownViewController; 51 | 52 | - (void)handleMemoryWarning; 53 | 54 | - (void)reloadDirectory; 55 | 56 | @end 57 | 58 | #pragma mark - 59 | 60 | // 61 | // LibraryDirectoryCell class interface 62 | // 63 | 64 | @interface LibraryDirectoryCell : ReaderThumbView 65 | 66 | - (void)showText:(NSString *)text; 67 | 68 | - (void)showCheck:(BOOL)checked; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Classes/LibraryDocumentsView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryDocumentsView.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbsView.h" 29 | 30 | @class LibraryDocumentsView; 31 | @class DocumentFolder; 32 | @class ReaderDocument; 33 | 34 | @protocol LibraryDocumentsDelegate 35 | 36 | @required // Delegate protocols 37 | 38 | - (void)documentsView:(LibraryDocumentsView *)documentsView didSelectReaderDocument:(ReaderDocument *)document; 39 | 40 | - (void)enableContainerScrollView:(BOOL)enabled; 41 | 42 | @end 43 | 44 | @interface LibraryDocumentsView : UIView 45 | 46 | @property (nonatomic, weak, readwrite) id delegate; 47 | 48 | @property (nonatomic, weak, readwrite) UIViewController *ownViewController; 49 | 50 | - (void)reloadDocumentsWithFolder:(DocumentFolder *)folder; 51 | 52 | - (void)refreshRecentDocuments; 53 | 54 | - (void)handleMemoryWarning; 55 | 56 | @end 57 | 58 | #pragma mark - 59 | 60 | // 61 | // LibraryDocumentsCell class interface 62 | // 63 | 64 | @interface LibraryDocumentsCell : ReaderThumbView 65 | 66 | - (CGSize)maximumContentSize; 67 | 68 | - (void)showText:(NSString *)text; 69 | 70 | - (void)showCheck:(BOOL)checked; 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /Classes/LibraryViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryViewController.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @class LibraryViewController; 29 | 30 | @protocol LibraryViewControllerDelegate 31 | 32 | @optional // Delegate protocols 33 | 34 | - (void)dismissLibraryViewController:(LibraryViewController *)viewController; 35 | 36 | @end 37 | 38 | @interface LibraryViewController : UIViewController 39 | 40 | @property (nonatomic, weak, readwrite) id delegate; 41 | 42 | @end 43 | 44 | #pragma mark - 45 | 46 | // 47 | // LibraryUpdatingView class interface 48 | // 49 | 50 | @interface LibraryUpdatingView : UIView 51 | 52 | - (void)animateHide; 53 | - (void)animateShow; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Classes/ViewerAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewerAppDelegate.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface ViewerAppDelegate : NSObject 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Classes/ViewerAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewerAppDelegate.m 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderConstants.h" 27 | #import "ViewerAppDelegate.h" 28 | #import "LibraryViewController.h" 29 | #import "DirectoryWatcher.h" 30 | #import "CoreDataManager.h" 31 | #import "DocumentsUpdate.h" 32 | #import "DocumentFolder.h" 33 | 34 | #include 35 | 36 | @interface ViewerAppDelegate () 37 | 38 | @end 39 | 40 | @implementation ViewerAppDelegate 41 | { 42 | UIWindow *mainWindow; // Main App Window 43 | 44 | LibraryViewController *rootViewController; 45 | 46 | DirectoryWatcher *directoryWatcher; 47 | 48 | NSTimer *directoryWatcherTimer; 49 | } 50 | 51 | #pragma mark Miscellaneous methods 52 | 53 | - (void)registerAppDefaults 54 | { 55 | NSNumber *hideStatusBar = [NSNumber numberWithBool:YES]; 56 | 57 | NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 58 | 59 | NSString *version = [infoDictionary objectForKey:(NSString *)kCFBundleVersionKey]; 60 | 61 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; // User defaults 62 | 63 | NSDictionary *defaults = [NSDictionary dictionaryWithObject:hideStatusBar forKey:kReaderSettingsHideStatusBar]; 64 | 65 | [userDefaults registerDefaults:defaults]; [userDefaults synchronize]; // Save user defaults 66 | 67 | [userDefaults setObject:version forKey:kReaderSettingsAppVersion]; // App version 68 | } 69 | 70 | - (void)prePopulateCoreData 71 | { 72 | NSManagedObjectContext *mainMOC = [[CoreDataManager sharedInstance] mainManagedObjectContext]; 73 | 74 | if ([DocumentFolder existsInMOC:mainMOC type:DocumentFolderTypeDefault] == NO) // Add default folder 75 | { 76 | NSString *folderName = NSLocalizedString(@"Documents", @"name"); // Localized default folder name 77 | 78 | [DocumentFolder insertInMOC:mainMOC name:folderName type:DocumentFolderTypeDefault]; // Insert it 79 | } 80 | 81 | if ([DocumentFolder existsInMOC:mainMOC type:DocumentFolderTypeRecent] == NO) // Add recent folder 82 | { 83 | NSString *folderName = NSLocalizedString(@"Recent", @"name"); // Localized recent folder name 84 | 85 | [DocumentFolder insertInMOC:mainMOC name:folderName type:DocumentFolderTypeRecent]; // Insert it 86 | } 87 | } 88 | 89 | #pragma mark UIApplicationDelegate methods 90 | 91 | - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url 92 | { 93 | return [[DocumentsUpdate sharedInstance] handleOpenURL:url]; 94 | } 95 | 96 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 97 | { 98 | [self registerAppDefaults]; // Register various application settings defaults 99 | 100 | [self prePopulateCoreData]; // Pre-populate Core Data store with various default objects 101 | 102 | if ((launchOptions != nil) && ([launchOptions objectForKey:UIApplicationLaunchOptionsURLKey] != nil)) 103 | { 104 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kReaderSettingsCurrentDocument]; // Clear 105 | } 106 | 107 | NSString *documentsPath = [DocumentsUpdate documentsPath]; // Application Documents path 108 | 109 | u_int8_t value = 1; // Value for iCloud and iTunes 'do not backup' item setxattr() function 110 | 111 | setxattr([documentsPath fileSystemRepresentation], "com.apple.MobileBackup", &value, 1, 0, 0); 112 | 113 | if ([[UIDevice currentDevice].systemVersion floatValue] >= 5.0f) // Only if iOS 5.0 and newer 114 | { 115 | directoryWatcher = [DirectoryWatcher watchFolderWithPath:documentsPath delegate:self]; 116 | } 117 | 118 | mainWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // Main application window 119 | 120 | mainWindow.backgroundColor = [UIColor grayColor]; // Neutral gray window background color 121 | 122 | rootViewController = [[LibraryViewController alloc] initWithNibName:nil bundle:nil]; // Root 123 | 124 | mainWindow.rootViewController = rootViewController; // Set the root view controller 125 | 126 | [mainWindow makeKeyAndVisible]; // Make it the key window and visible 127 | 128 | return YES; 129 | } 130 | 131 | - (void)applicationWillResignActive:(UIApplication *)application 132 | { 133 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of 134 | // temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application 135 | // and it begins the transition to the background state. Use this method to pause ongoing tasks, disable timers, 136 | // and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 137 | 138 | [[NSUserDefaults standardUserDefaults] synchronize]; // Save user defaults 139 | } 140 | 141 | - (void)applicationDidEnterBackground:(UIApplication *)application 142 | { 143 | // Use this method to release shared resources, save user data, invalidate timers, and store enough 144 | // application state information to restore your application to its current state in case it is terminated later. 145 | // If your application supports background execution, called instead of applicationWillTerminate: when the user quits. 146 | } 147 | 148 | - (void)applicationWillEnterForeground:(UIApplication *)application 149 | { 150 | // Called as part of transition from the background to the inactive state: here you can undo many 151 | // of the changes made on entering the background. 152 | } 153 | 154 | - (void)applicationDidBecomeActive:(UIApplication *)application 155 | { 156 | // Restart any tasks that were paused (or not yet started) while the application was inactive. 157 | // If the application was previously in the background, optionally refresh the user interface. 158 | 159 | [[DocumentsUpdate sharedInstance] queueDocumentsUpdate]; // Queue a documents update 160 | } 161 | 162 | - (void)applicationWillTerminate:(UIApplication *)application 163 | { 164 | // Called when the application is about to terminate. 165 | // See also applicationDidEnterBackground:. 166 | 167 | [[NSUserDefaults standardUserDefaults] synchronize]; // Save user defaults 168 | } 169 | 170 | - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application 171 | { 172 | // Free up as much memory as possible by purging cached data objects that can be recreated 173 | // (or reloaded from disk) later. 174 | 175 | NSLog(@"%s", __FUNCTION__); 176 | } 177 | 178 | #pragma mark ViewerAppDelegate instance methods 179 | 180 | - (void)dealloc 181 | { 182 | [directoryWatcherTimer invalidate]; 183 | } 184 | 185 | #pragma mark DirectoryWatcherDelegate methods 186 | 187 | - (void)directoryDidChange:(DirectoryWatcher *)folderWatcher 188 | { 189 | if (directoryWatcherTimer != nil) { [directoryWatcherTimer invalidate]; directoryWatcherTimer = nil; } // Invalidate and release previous timer 190 | 191 | directoryWatcherTimer = [NSTimer scheduledTimerWithTimeInterval:4.8 target:self selector:@selector(watcherTimerFired:) userInfo:nil repeats:NO]; 192 | } 193 | 194 | - (void)watcherTimerFired:(NSTimer *)timer 195 | { 196 | [directoryWatcherTimer invalidate]; directoryWatcherTimer = nil; // Invalidate and release timer 197 | 198 | [[DocumentsUpdate sharedInstance] queueDocumentsUpdate]; // Queue a documents update 199 | } 200 | 201 | @end 202 | -------------------------------------------------------------------------------- /CoreData/CoreDataManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataManager.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface CoreDataManager : NSObject 29 | 30 | + (CoreDataManager *)sharedInstance; 31 | 32 | - (NSManagedObjectModel *)mainManagedObjectModel; 33 | - (NSPersistentStoreCoordinator *)mainPersistentStoreCoordinator; 34 | - (NSManagedObjectContext *)mainManagedObjectContext; 35 | - (NSManagedObjectContext *)newManagedObjectContext; 36 | 37 | - (void)saveMainManagedObjectContext; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /CoreData/CoreDataManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreDataManager.m 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "CoreDataManager.h" 27 | 28 | @implementation CoreDataManager 29 | { 30 | NSManagedObjectModel *mainManagedObjectModel; 31 | 32 | NSPersistentStoreCoordinator *mainPersistentStoreCoordinator; 33 | 34 | NSManagedObjectContext *mainManagedObjectContext; 35 | } 36 | 37 | #pragma mark CoreDataManager class methods 38 | 39 | + (CoreDataManager *)sharedInstance 40 | { 41 | static dispatch_once_t predicate = 0; 42 | 43 | static CoreDataManager *object = nil; // Object 44 | 45 | dispatch_once(&predicate, ^{ object = [self new]; }); 46 | 47 | return object; // CoreDataManager singleton 48 | } 49 | 50 | + (NSURL *)applicationDocumentsDirectory 51 | { 52 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 53 | 54 | return [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0]; 55 | } 56 | 57 | + (NSURL *)applicationSupportDirectory 58 | { 59 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 60 | 61 | return [fileManager URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL]; 62 | } 63 | 64 | + (NSURL *)applicationCoreDataStoreFileURL 65 | { 66 | return [[CoreDataManager applicationSupportDirectory] URLByAppendingPathComponent:@"Reader.sqlite"]; // Data store file URL 67 | } 68 | 69 | #pragma mark CoreDataManager instance methods 70 | 71 | - (NSManagedObjectModel *)mainManagedObjectModel 72 | { 73 | if (mainManagedObjectModel == nil) // Create ManagedObjectModel 74 | { 75 | assert([NSThread isMainThread] == YES); // Create it only on the main thread 76 | 77 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Reader" withExtension:@"momd"]; 78 | 79 | mainManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 80 | } 81 | 82 | return mainManagedObjectModel; 83 | } 84 | 85 | - (NSPersistentStoreCoordinator *)mainPersistentStoreCoordinator 86 | { 87 | if (mainPersistentStoreCoordinator == nil) // Create PersistentStoreCoordinator 88 | { 89 | assert([NSThread isMainThread] == YES); // Create it only on the main thread 90 | 91 | NSURL *storeURL = [CoreDataManager applicationCoreDataStoreFileURL]; // DB 92 | 93 | __autoreleasing NSError *error = nil; // Error information object 94 | 95 | NSDictionary *migrate = [NSDictionary dictionaryWithObjectsAndKeys: 96 | [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 97 | [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 98 | 99 | mainPersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self mainManagedObjectModel]]; 100 | 101 | if ([mainPersistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:migrate error:&error] == nil) 102 | { 103 | // Replace this implementation with code to handle the error appropriately. 104 | 105 | // assert() causes the application to generate a crash log and terminate. You should not use this function in a 106 | // shipping application, although it may be useful during development. If it is not possible to recover from the 107 | // error, display an alert panel that instructs the user to quit the application by pressing the Home button. 108 | 109 | // Typical reasons for an error here include: 110 | // * The persistent store is not accessible; 111 | // * The schema for the persistent store is incompatible with current managed object model. 112 | // Check the error message to determine what the actual problem was. 113 | 114 | // If the persistent store is not accessible, there is typically something wrong with the file path. 115 | // Often, a file URL is pointing into the application's resources directory instead of a writeable directory. 116 | 117 | // If you encounter schema incompatibility errors during development, you can reduce their frequency by: 118 | // * Simply deleting the existing store: 119 | // [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil] 120 | 121 | // * Performing automatic lightweight migration by passing the following dictionary as the options parameter: 122 | // [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 123 | // [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 124 | 125 | // Lightweight migration will only work for a limited set of schema changes. 126 | // Consult "Core Data Model Versioning and Data Migration Programming Guide" for details. 127 | 128 | NSLog(@"%s %@", __FUNCTION__, error); assert(NO); 129 | } 130 | } 131 | 132 | return mainPersistentStoreCoordinator; 133 | } 134 | 135 | - (NSManagedObjectContext *)mainManagedObjectContext 136 | { 137 | if (mainManagedObjectContext == nil) // Create ManagedObjectContext 138 | { 139 | assert([NSThread isMainThread] == YES); // Create it only on the main thread 140 | 141 | NSPersistentStoreCoordinator *coordinator = [self mainPersistentStoreCoordinator]; 142 | 143 | if (coordinator != nil) // Check for valid PersistentStoreCoordinator 144 | { 145 | mainManagedObjectContext = [NSManagedObjectContext new]; // New MOC 146 | 147 | [mainManagedObjectContext setPersistentStoreCoordinator:coordinator]; 148 | } 149 | } 150 | 151 | return mainManagedObjectContext; 152 | } 153 | 154 | - (NSManagedObjectContext *)newManagedObjectContext 155 | { 156 | NSManagedObjectContext *someManagedObjectContext = nil; 157 | 158 | NSPersistentStoreCoordinator *coordinator = [self mainPersistentStoreCoordinator]; 159 | 160 | if (coordinator != nil) // Check for valid PersistentStoreCoordinator 161 | { 162 | someManagedObjectContext = [NSManagedObjectContext new]; // New MOC 163 | 164 | [someManagedObjectContext setPersistentStoreCoordinator:coordinator]; 165 | } 166 | 167 | return someManagedObjectContext; 168 | } 169 | 170 | - (void)saveMainManagedObjectContext 171 | { 172 | assert([NSThread isMainThread] == YES); // Main thread only 173 | 174 | if (mainManagedObjectContext != nil) // Save ManagedObjectContext 175 | { 176 | __autoreleasing NSError *error = nil; // Error information object 177 | 178 | if ([mainManagedObjectContext hasChanges] == YES) // Save changes 179 | { 180 | if ([mainManagedObjectContext save:&error] == NO) // Log any errors 181 | { 182 | // Replace this implementation with code to handle the error appropriately. 183 | 184 | // assert() causes the application to generate a crash log and terminate. You should not use this function in a 185 | // shipping application, although it may be useful during development. If it is not possible to recover from the 186 | // error, display an alert panel that instructs the user to quit the application by pressing the Home button. 187 | 188 | NSLog(@"%s %@", __FUNCTION__, error); assert(NO); 189 | } 190 | } 191 | } 192 | } 193 | 194 | @end 195 | -------------------------------------------------------------------------------- /CoreData/DocumentFolder.h: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentFolder.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @class ReaderDocument; 29 | 30 | typedef NS_ENUM(NSInteger, DocumentFolderType) 31 | { 32 | DocumentFolderTypeUser = 0, 33 | DocumentFolderTypeDefault = 1, 34 | DocumentFolderTypeRecent = 2 35 | }; 36 | 37 | @interface DocumentFolder : NSManagedObject 38 | 39 | @property (nonatomic, strong, readwrite) NSString *name; 40 | @property (nonatomic, strong, readwrite) NSNumber *type; 41 | @property (nonatomic, strong, readwrite) NSSet *documents; 42 | @property (nonatomic, assign, readwrite) BOOL isChecked; 43 | 44 | + (NSArray *)allInMOC:(NSManagedObjectContext *)inMOC; 45 | + (BOOL)existsInMOC:(NSManagedObjectContext *)inMOC name:(NSString *)string; 46 | + (BOOL)existsInMOC:(NSManagedObjectContext *)inMOC type:(DocumentFolderType)kind; 47 | + (DocumentFolder *)folderInMOC:(NSManagedObjectContext *)inMOC type:(DocumentFolderType)kind; 48 | + (DocumentFolder *)insertInMOC:(NSManagedObjectContext *)inMOC name:(NSString *)string type:(DocumentFolderType)kind; 49 | + (void)renameInMOC:(NSManagedObjectContext *)inMOC objectID:(NSManagedObjectID *)objectID name:(NSString *)string; 50 | + (void)deleteInMOC:(NSManagedObjectContext *)inMOC objectID:(NSManagedObjectID *)objectID; 51 | 52 | extern NSString *const DocumentFolderAddedNotification; 53 | extern NSString *const DocumentFolderRenamedNotification; 54 | extern NSString *const DocumentFolderDeletedNotification; 55 | extern NSString *const DocumentFolderNotificationObjectID; 56 | extern NSString *const DocumentFoldersDeletedNotification; 57 | 58 | @end 59 | 60 | @interface DocumentFolder (CoreDataGeneratedAccessors) 61 | 62 | - (void)addDocumentsObject:(ReaderDocument *)value; 63 | - (void)removeDocumentsObject:(ReaderDocument *)value; 64 | - (void)addDocuments:(NSSet *)value; 65 | - (void)removeDocuments:(NSSet *)value; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /CoreData/DocumentFolder.m: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentFolder.m 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "DocumentFolder.h" 27 | #import "ReaderDocument.h" 28 | 29 | @implementation DocumentFolder 30 | 31 | #pragma mark Constants 32 | 33 | #define kDocumentFolder @"DocumentFolder" 34 | 35 | #pragma mark Properties 36 | 37 | @dynamic name; 38 | @dynamic type; 39 | @dynamic documents; 40 | @synthesize isChecked; 41 | 42 | #pragma mark DocumentFolder Core Data class methods 43 | 44 | + (NSArray *)allInMOC:(NSManagedObjectContext *)inMOC 45 | { 46 | assert(inMOC != nil); // Check parameter 47 | 48 | NSFetchRequest *request = [NSFetchRequest new]; // Fetch request instance 49 | 50 | [request setEntity:[NSEntityDescription entityForName:kDocumentFolder inManagedObjectContext:inMOC]]; 51 | 52 | NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; 53 | 54 | [request setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]]; // Sort order 55 | 56 | [request setReturnsObjectsAsFaults:NO]; [request setFetchBatchSize:24]; // Optimize fetch 57 | 58 | __autoreleasing NSError *error = nil; // Error information object 59 | 60 | NSArray *objectList = [inMOC executeFetchRequest:request error:&error]; 61 | 62 | if (objectList == nil) { NSLog(@"%s %@", __FUNCTION__, error); assert(NO); } 63 | 64 | return objectList; 65 | } 66 | 67 | + (BOOL)existsInMOC:(NSManagedObjectContext *)inMOC name:(NSString *)string 68 | { 69 | assert(inMOC != nil); assert(string != nil); // Check parameters 70 | 71 | NSFetchRequest *request = [NSFetchRequest new]; // Fetch request instance 72 | 73 | [request setEntity:[NSEntityDescription entityForName:kDocumentFolder inManagedObjectContext:inMOC]]; 74 | 75 | [request setPredicate:[NSPredicate predicateWithFormat:@"name == %@", string]]; // Name predicate 76 | 77 | __autoreleasing NSError *error = nil; // Error information object 78 | 79 | NSUInteger count = [inMOC countForFetchRequest:request error:&error]; 80 | 81 | if (error != nil) { NSLog(@"%s %@", __FUNCTION__, error); assert(NO); } 82 | 83 | return ((count > 0) ? YES : NO); 84 | } 85 | 86 | + (BOOL)existsInMOC:(NSManagedObjectContext *)inMOC type:(DocumentFolderType)kind 87 | { 88 | assert(inMOC != nil); // Check parameter 89 | 90 | NSFetchRequest *request = [NSFetchRequest new]; // Fetch request instance 91 | 92 | [request setEntity:[NSEntityDescription entityForName:kDocumentFolder inManagedObjectContext:inMOC]]; 93 | 94 | [request setPredicate:[NSPredicate predicateWithFormat:@"type == %d", kind]]; // Type predicate 95 | 96 | __autoreleasing NSError *error = nil; // Error information object 97 | 98 | NSUInteger count = [inMOC countForFetchRequest:request error:&error]; 99 | 100 | if (error != nil) { NSLog(@"%s %@", __FUNCTION__, error); assert(NO); } 101 | 102 | return ((count > 0) ? YES : NO); 103 | } 104 | 105 | + (DocumentFolder *)folderInMOC:(NSManagedObjectContext *)inMOC type:(DocumentFolderType)kind 106 | { 107 | assert(inMOC != nil); // Check parameter 108 | 109 | NSFetchRequest *request = [NSFetchRequest new]; // Fetch request instance 110 | 111 | [request setEntity:[NSEntityDescription entityForName:kDocumentFolder inManagedObjectContext:inMOC]]; 112 | 113 | [request setPredicate:[NSPredicate predicateWithFormat:@"type == %d", kind]]; // Type predicate 114 | 115 | [request setReturnsObjectsAsFaults:NO]; //[request setFetchBatchSize:24]; // Optimize fetch 116 | 117 | __autoreleasing NSError *error = nil; // Error information object 118 | 119 | NSArray *objectList = [inMOC executeFetchRequest:request error:&error]; 120 | 121 | if (objectList == nil) { NSLog(@"%s %@", __FUNCTION__, error); assert(NO); } 122 | 123 | return [objectList lastObject]; 124 | } 125 | 126 | + (DocumentFolder *)insertInMOC:(NSManagedObjectContext *)inMOC name:(NSString *)string type:(DocumentFolderType)kind 127 | { 128 | assert(inMOC != nil); assert(string != nil); // Check parameters 129 | 130 | DocumentFolder *object = [NSEntityDescription insertNewObjectForEntityForName:kDocumentFolder inManagedObjectContext:inMOC]; 131 | 132 | if ((object != nil) && ([object isMemberOfClass:[DocumentFolder class]])) // Valid DocumentFolder object 133 | { 134 | object.name = string; object.type = [NSNumber numberWithInteger:kind]; // Set name and type 135 | 136 | __autoreleasing NSError *error = nil; // Error information object 137 | 138 | if ([inMOC hasChanges] == YES) // Save changes 139 | { 140 | if ([inMOC save:&error] == YES) // Did save changes 141 | { 142 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 143 | 144 | NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[object objectID] forKey:DocumentFolderNotificationObjectID]; 145 | 146 | [notificationCenter postNotificationName:DocumentFolderAddedNotification object:nil userInfo:userInfo]; 147 | } 148 | else // Log any errors 149 | { 150 | NSLog(@"%s %@", __FUNCTION__, error); assert(NO); 151 | } 152 | } 153 | } 154 | 155 | return object; 156 | } 157 | 158 | + (void)renameInMOC:(NSManagedObjectContext *)inMOC objectID:(NSManagedObjectID *)objectID name:(NSString *)string 159 | { 160 | assert(inMOC != nil); assert(objectID != nil); assert(string != nil); // Check parameters 161 | 162 | DocumentFolder *object = (id)[inMOC existingObjectWithID:objectID error:NULL]; // Get object 163 | 164 | if ((object != nil) && ([object isMemberOfClass:[DocumentFolder class]])) // Valid object 165 | { 166 | object.name = string; // Update folder name 167 | 168 | __autoreleasing NSError *error = nil; // Error information object 169 | 170 | if ([inMOC hasChanges] == YES) // Save changes 171 | { 172 | if ([inMOC save:&error] == YES) // Did save changes 173 | { 174 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 175 | 176 | NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[object objectID] forKey:DocumentFolderNotificationObjectID]; 177 | 178 | [notificationCenter postNotificationName:DocumentFolderRenamedNotification object:nil userInfo:userInfo]; 179 | } 180 | else // Log any errors 181 | { 182 | NSLog(@"%s %@", __FUNCTION__, error); assert(NO); 183 | } 184 | } 185 | } 186 | } 187 | 188 | + (void)deleteInMOC:(NSManagedObjectContext *)inMOC objectID:(NSManagedObjectID *)objectID 189 | { 190 | assert(inMOC != nil); assert(objectID != nil); // Check parameters 191 | 192 | DocumentFolder *object = (id)[inMOC existingObjectWithID:objectID error:NULL]; // Get object 193 | 194 | if ((object != nil) && ([object isMemberOfClass:[DocumentFolder class]])) // Valid object 195 | { 196 | [inMOC deleteObject:object]; // Delete object 197 | 198 | __autoreleasing NSError *error = nil; // Error information object 199 | 200 | if ([inMOC hasChanges] == YES) // Save changes 201 | { 202 | if ([inMOC save:&error] == YES) // Did save changes 203 | { 204 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 205 | 206 | NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[object objectID] forKey:DocumentFolderNotificationObjectID]; 207 | 208 | [notificationCenter postNotificationName:DocumentFolderDeletedNotification object:nil userInfo:userInfo]; 209 | } 210 | else // Log any errors 211 | { 212 | NSLog(@"%s %@", __FUNCTION__, error); assert(NO); 213 | } 214 | } 215 | } 216 | } 217 | 218 | #pragma mark DocumentFolder Core Data instance methods 219 | 220 | - (void)willTurnIntoFault 221 | { 222 | self.isChecked = NO; 223 | } 224 | 225 | #pragma mark Notification name strings 226 | 227 | NSString *const DocumentFolderAddedNotification = @"DocumentFolderAddedNotification"; 228 | NSString *const DocumentFolderRenamedNotification = @"DocumentFolderRenamedNotification"; 229 | NSString *const DocumentFolderDeletedNotification = @"DocumentFolderDeletedNotification"; 230 | NSString *const DocumentFolderNotificationObjectID = @"DocumentFolderNotificationObjectID"; 231 | NSString *const DocumentFoldersDeletedNotification = @"DocumentFoldersDeletedNotification"; 232 | 233 | @end 234 | -------------------------------------------------------------------------------- /CoreData/ReaderDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderDocument.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @class DocumentFolder; 29 | 30 | @interface ReaderDocument : NSManagedObject 31 | 32 | @property (nonatomic, strong, readwrite) NSString *guid; 33 | @property (nonatomic, strong, readwrite) NSURL *fileURL; 34 | @property (nonatomic, strong, readwrite) NSString *fileName; 35 | @property (nonatomic, strong, readwrite) NSString *filePath; 36 | @property (nonatomic, strong, readwrite) NSString *password; 37 | @property (nonatomic, strong, readwrite) NSNumber *pageCount; 38 | @property (nonatomic, strong, readwrite) NSNumber *pageNumber; 39 | @property (nonatomic, strong, readwrite) NSNumber *fileSize; 40 | @property (nonatomic, strong, readwrite) NSDate *fileDate; 41 | @property (nonatomic, strong, readwrite) NSDate *lastOpen; 42 | @property (nonatomic, strong, readwrite) NSData *tagData; 43 | @property (nonatomic, strong, readwrite) NSManagedObject *folder; 44 | @property (nonatomic, strong, readonly) NSMutableIndexSet *bookmarks; 45 | @property (nonatomic, assign, readwrite) BOOL isChecked; 46 | 47 | @property (nonatomic, readonly) BOOL canEmail; 48 | @property (nonatomic, readonly) BOOL canExport; 49 | @property (nonatomic, readonly) BOOL canPrint; 50 | 51 | + (NSArray *)allInMOC:(NSManagedObjectContext *)inMOC; 52 | + (NSArray *)allInMOC:(NSManagedObjectContext *)inMOC withName:(NSString *)name; 53 | + (NSArray *)allInMOC:(NSManagedObjectContext *)inMOC withFolder:(DocumentFolder *)object; 54 | + (ReaderDocument *)insertInMOC:(NSManagedObjectContext *)inMOC name:(NSString *)name path:(NSString *)path; 55 | + (void)renameInMOC:(NSManagedObjectContext *)inMOC object:(ReaderDocument *)object name:(NSString *)string; 56 | + (void)deleteInMOC:(NSManagedObjectContext *)inMOC object:(ReaderDocument *)object fm:(NSFileManager *)fm; 57 | + (BOOL)existsInMOC:(NSManagedObjectContext *)inMOC name:(NSString *)string; 58 | 59 | - (void)updateDocumentProperties; 60 | - (void)archiveDocumentProperties; 61 | - (BOOL)fileExistsAndValid; 62 | 63 | //extern NSString *const ReaderDocumentAddedNotification; 64 | extern NSString *const ReaderDocumentRenamedNotification; 65 | //extern NSString *const ReaderDocumentDeletedNotification; 66 | extern NSString *const ReaderDocumentNotificationObjectID; 67 | 68 | @end 69 | 70 | @interface ReaderDocument (CoreDataPrimitiveAccessors) 71 | 72 | - (NSURL *)primitiveFileURL; 73 | - (void)setPrimitiveFileURL:(NSURL *)url; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /Graphics/AppIcon-057.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-057.png -------------------------------------------------------------------------------- /Graphics/AppIcon-072.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-072.png -------------------------------------------------------------------------------- /Graphics/AppIcon-076.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-076.png -------------------------------------------------------------------------------- /Graphics/AppIcon-114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-114.png -------------------------------------------------------------------------------- /Graphics/AppIcon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-120.png -------------------------------------------------------------------------------- /Graphics/AppIcon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-144.png -------------------------------------------------------------------------------- /Graphics/AppIcon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-152.png -------------------------------------------------------------------------------- /Graphics/AppIcon-167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-167.png -------------------------------------------------------------------------------- /Graphics/AppIcon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-180.png -------------------------------------------------------------------------------- /Graphics/AppIcon-PDF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/AppIcon-PDF.png -------------------------------------------------------------------------------- /Graphics/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Default-568h@2x.png -------------------------------------------------------------------------------- /Graphics/Folder-Large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Folder-Large.png -------------------------------------------------------------------------------- /Graphics/Folder-Large@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Folder-Large@2x.png -------------------------------------------------------------------------------- /Graphics/Folder-Large@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Folder-Large@3x.png -------------------------------------------------------------------------------- /Graphics/Folder-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Folder-Small.png -------------------------------------------------------------------------------- /Graphics/Folder-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Folder-Small@2x.png -------------------------------------------------------------------------------- /Graphics/Folder-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Folder-Small@3x.png -------------------------------------------------------------------------------- /Graphics/Icon-Check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Check.png -------------------------------------------------------------------------------- /Graphics/Icon-Check@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Check@2x.png -------------------------------------------------------------------------------- /Graphics/Icon-Check@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Check@3x.png -------------------------------------------------------------------------------- /Graphics/Icon-Checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Checked.png -------------------------------------------------------------------------------- /Graphics/Icon-Checked@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Checked@2x.png -------------------------------------------------------------------------------- /Graphics/Icon-Checked@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Checked@3x.png -------------------------------------------------------------------------------- /Graphics/Icon-Cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Cross.png -------------------------------------------------------------------------------- /Graphics/Icon-Cross@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Cross@2x.png -------------------------------------------------------------------------------- /Graphics/Icon-Cross@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Cross@3x.png -------------------------------------------------------------------------------- /Graphics/Icon-Edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Edit.png -------------------------------------------------------------------------------- /Graphics/Icon-Edit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Edit@2x.png -------------------------------------------------------------------------------- /Graphics/Icon-Edit@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Edit@3x.png -------------------------------------------------------------------------------- /Graphics/Icon-Folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Folder.png -------------------------------------------------------------------------------- /Graphics/Icon-Folder@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Folder@2x.png -------------------------------------------------------------------------------- /Graphics/Icon-Folder@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Folder@3x.png -------------------------------------------------------------------------------- /Graphics/Icon-Minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Minus.png -------------------------------------------------------------------------------- /Graphics/Icon-Minus@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Minus@2x.png -------------------------------------------------------------------------------- /Graphics/Icon-Minus@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Minus@3x.png -------------------------------------------------------------------------------- /Graphics/Icon-Plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Plus.png -------------------------------------------------------------------------------- /Graphics/Icon-Plus@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Plus@2x.png -------------------------------------------------------------------------------- /Graphics/Icon-Plus@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Icon-Plus@3x.png -------------------------------------------------------------------------------- /Graphics/Reader-Button-H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Button-H.png -------------------------------------------------------------------------------- /Graphics/Reader-Button-H@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Button-H@2x.png -------------------------------------------------------------------------------- /Graphics/Reader-Button-H@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Button-H@3x.png -------------------------------------------------------------------------------- /Graphics/Reader-Button-N.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Button-N.png -------------------------------------------------------------------------------- /Graphics/Reader-Button-N@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Button-N@2x.png -------------------------------------------------------------------------------- /Graphics/Reader-Button-N@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Button-N@3x.png -------------------------------------------------------------------------------- /Graphics/Reader-Email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Email.png -------------------------------------------------------------------------------- /Graphics/Reader-Email@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Email@2x.png -------------------------------------------------------------------------------- /Graphics/Reader-Email@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Email@3x.png -------------------------------------------------------------------------------- /Graphics/Reader-Mark-N.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Mark-N.png -------------------------------------------------------------------------------- /Graphics/Reader-Mark-N@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Mark-N@2x.png -------------------------------------------------------------------------------- /Graphics/Reader-Mark-N@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Mark-N@3x.png -------------------------------------------------------------------------------- /Graphics/Reader-Mark-Y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Mark-Y.png -------------------------------------------------------------------------------- /Graphics/Reader-Mark-Y@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Mark-Y@2x.png -------------------------------------------------------------------------------- /Graphics/Reader-Mark-Y@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Mark-Y@3x.png -------------------------------------------------------------------------------- /Graphics/Reader-Print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Print.png -------------------------------------------------------------------------------- /Graphics/Reader-Print@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Print@2x.png -------------------------------------------------------------------------------- /Graphics/Reader-Print@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Print@3x.png -------------------------------------------------------------------------------- /Graphics/Reader-Thumbs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Thumbs.png -------------------------------------------------------------------------------- /Graphics/Reader-Thumbs@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Thumbs@2x.png -------------------------------------------------------------------------------- /Graphics/Reader-Thumbs@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Graphics/Reader-Thumbs@3x.png -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | 2 | ## History 3 | 4 | 2016-01-25: Version 1.2.2 5 | 6 | - Added iOS 9 and iPad Pro support. 7 | - iPhone 6 Plus and iPhone 6S Plus @3x graphics. 8 | - Pulled in PDF Reader Core for iOS v2.8.7 code. 9 | 10 | 2015-06-28: Version 1.2.1 11 | 12 | - Pulled in PDF Reader Core for iOS v2.8.6 code. 13 | - iPhone 6 and 6 Plus support - launch images and thumbnails. 14 | - Added support for compile time READER_FLAT_UI option. 15 | 16 | 2014-09-28: Version 1.2.0 17 | 18 | - Pulled in PDF Reader Core for iOS v2.8.3 code. 19 | - Cleaned up 64-bit code build compiler warnings. 20 | 21 | 2013-11-19: Version 1.1.3 22 | 23 | - Retina and zoom levels bug fixes. 24 | - PDF annotation URI handling bug fix. 25 | 26 | 2013-10-24: Version 1.1.2 27 | 28 | - iOS 7 status bar handling bug fixes. 29 | 30 | 2013-10-12: Version 1.1.1 31 | 32 | - Changed 'unsafe_unretained' to 'weak'. 33 | 34 | 2013-10-03: Version 1.1.0 35 | 36 | - iOS 7 and Xcode 5.0 support. 37 | - Pulled in PDF Reader Core for iOS v2.7.0 code. 38 | 39 | 2013-06-05: Version 1.0.2 40 | 41 | - Set UIButton exclusiveTouch property to YES. 42 | - Pulled in PDF Reader Core for iOS v2.6.2 code. 43 | 44 | 2012-10-05: Version 1.0.1 45 | 46 | - Pulled in PDF Reader Core for iOS v2.6.1 code. 47 | 48 | 2012-09-26: Version 1.0.0 49 | 50 | - Released PDF Viewer App v1.0.0 into the wild. 51 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | Copyright © 2011-2016 Julius Oklamcak. All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 | of the Software, and to permit persons to whom the Software is furnished to 9 | do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | -=-=-=- 22 | 23 | iOS, iPad, iPhone, iPod touch are registered trademarks of Apple Inc. 24 | All other trademarks and service marks are the properties of their 25 | respective owners. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### PDF Viewer App for iOS 2 | 3 | --- 4 | 5 | *This project is no longer supported or maintained. It is only here for historical reasons. 6 | Please see the [UXReader PDF Framework for iOS](https://github.com/vfr/UXReader-iOS) project for a possible replacement.* 7 | 8 | --- 9 | 10 | ### Introduction 11 | 12 | This iOS PDF viewer app is based on the open source iOS PDF reader 13 | code from the https://github.com/vfr/Reader repository on GitHub. 14 | 15 | ### Features 16 | 17 | - Universal: runs on iPad, iPhone and iPod touch. 18 | - Uses Core Data to keep track of PDF documents. 19 | - PDF documents can be organized into folders. 20 | - Supports iTunes File Sharing for file transfers. 21 | - Handles "Open In..." from other apps (Mail, etc). 22 | - Multithreaded giving it a responsive UI. 23 | - In-App HTML-based help. 24 | - Localization ready. 25 | - iBooks-like document navigation. 26 | - Device rotation and all orientations. 27 | - Encrypted (password protected) PDFs. 28 | - PDF links (URI and go to page). 29 | - PDFs with rotated pages. 30 | 31 | ### Notes 32 | 33 | Current development and testing of the PDF Viewer App is under Xcode 7.2, 34 | LLVM 7.0 and iOS 9.2. The code uses ARC memory management and should work 35 | under iOS 6 as well. 36 | 37 | Please see https://github.com/vfr/Reader/blob/master/README.md for notes 38 | on the core code that the PDF Viewer App uses. 39 | 40 | ### Contact Info 41 | 42 | Email: joklamcak(at)gmail(dot)com 43 | 44 | Twitter: [@joklamcak](https://twitter.com/joklamcak) 45 | 46 | ### License 47 | 48 | This code has been made available under the MIT License. 49 | 50 | ### Screen Captures 51 | 52 | ![iPad Page](http://i.imgur.com/jaeCPz1.png)

53 | ![iPad Thumbs](http://i.imgur.com/1b4kY9s.png)

54 | ![iPod Page](http://i.imgur.com/y8wWRDN.png)

55 | ![iPod Thumbs](http://i.imgur.com/nddT2RP.png)

56 | -------------------------------------------------------------------------------- /Reader.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | Reader.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Reader.xcdatamodeld/Reader.xcdatamodel/elements: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Reader.xcdatamodeld/Reader.xcdatamodel/elements -------------------------------------------------------------------------------- /Reader.xcdatamodeld/Reader.xcdatamodel/layout: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Reader.xcdatamodeld/Reader.xcdatamodel/layout -------------------------------------------------------------------------------- /Resources/Settings.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | StringsTable 6 | Root 7 | PreferenceSpecifiers 8 | 9 | 10 | Type 11 | PSToggleSwitchSpecifier 12 | Title 13 | HideStatusBar 14 | Key 15 | HideStatusBar 16 | DefaultValue 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Resources/Settings.bundle/en.lproj/Root.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Resources/Settings.bundle/en.lproj/Root.strings -------------------------------------------------------------------------------- /Resources/Viewer-App.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfr/Viewer/6fa6e75ebda8fe22520d99df204847b1226e01bb/Resources/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /Resources/en.lproj/help.css: -------------------------------------------------------------------------------- 1 | /*!*/ 2 | -------------------------------------------------------------------------------- /Resources/en.lproj/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Viewer In-App Help 7 | 8 | 9 |

Getting Started with Viewer

10 |

Before you can begin using Viewer to view your PDF files, you need to connect your device to your computer via USB cable and copy (sync) them over to it using iTunes. Once you have done that, from within Viewer, tap the Documents folder in the Library. Now simply scroll to and tap on the PDF document that you wish to view.

11 |

Viewer also supports Open In... from Mail and other Apps. In Mail, press and hold on a PDF attachment. When the popup appears, tap Open In... and then tap Viewer in the list. The document will open in Viewer and will also be found in the Documents folder.

12 |

Navigating Documents

13 |

To go to the next page of a document, tap in the right hand side of the screen near the edge (or swipe, or drag from right to left), to go back a page, tap in the left hand side of the screen near the edge (or swipe, or drag from left to right).

14 |

To zoom in, either double-tap with one finger in the middle of the screen or use a zoom in pinch gesture. To zoom out, double-tap with two fingers in the middle of the screen or use a zoom out pinch gesture. When zoomed in, pan the page around by holding your finger down and moving it.

15 |

To display the menu and page bars, tap once in the middle of the screen.

16 |

To quickly move around in a document, tap on the small thumbnails in the page bar on the bottom of the screen. You can also drag the slightly larger page thumbnail back and forth.

17 |

Syncing PDF Files

18 |

You need iTunes installed on your computer to be able to copy (sync) PDF files to your device:

19 |

1) Connect your device to your computer with its USB cable.

20 |

2) In iTunes, click on your device just below DEVICES.

21 |

3) Now select the Apps tab.

22 |

4) Scroll down to the File Sharing section and click on Viewer.

23 |

5) Click the Add... button and choose the PDF file (or files) that you want to sync (copy over) to your device in the Open window and click the Open button. iTunes will now sync the PDF files over to your device.

24 |

6) Open Viewer on your device and tap the Documents folder.

25 |

Please note that any PDF files that you sync over to your device will be backed up to iCloud if you have enabled that feature on your device. This could take some time and will use up some amount of your allotment of storage space.

26 |

Adding Folders

27 |

Viewer allows PDFs to be organized into folders. To create a new folder, tap the plus symbol in the Library toolbar. Enter in a new folder name and tap the Done button.

28 |

Deleting Folders

29 |

To delete folders (but not their contents), tap the check mark symbol in the Library toolbar. Tap the folders that you wish to delete (a check mark will appear in the top right corner of each folder) and then tap the minus symbol in the Library toolbar. Tap Delete to confirm the deletion. Any PDFs in the deleted folders will automatically be moved back into the Documents folder. To cancel folder selection, tap the cross symbol in the Library toolbar.

30 |

Please note that the Documents and Recent folders cannot be deleted, only renamed.

31 |

Renaming Folders

32 |

To rename a folder, tap the check mark symbol in the Library toolbar. Tap on the folder that you wish to rename and then tap the keyboard icon in the Library toolbar. If you select more than one folder, the keyboard icon will be disabled as you can only rename one folder at a time. Enter in a new name, or edit the existing one and tap the Done button.

33 |

Moving PDFs to Folders

34 |

After having created a new folder, you can move PDFs from any other folder into it to organize your collection of documents.

35 |

For example: Tap the Documents folder in the Library. Tap the check mark symbol in the folder toolbar. Tap the PDFs that you wish to move (a check mark will appear in the top right corner of each PDF thumbnail) and then tap the folder icon in the folder toolbar. Tap the folder that you wish all of the selected PDFs to be moved into. To cancel PDF selection, tap the cross symbol in the folder toolbar.

36 |

Recent Folder

37 |

The Recent folder keeps track of the most recently viewed documents (most recent to least recent). To clear documents from the Recent folder, tap the check mark symbol in the folder toolbar. Tap the PDFs that you wish to remove (a check mark will appear in the top right corner of each PDF thumbnail) and then tap the folder icon in the folder toolbar.

38 |

Renaming PDFs

39 |

To rename a PDF, tap the check mark symbol in the toolbar when in a folder. Tap on the PDF that you wish to rename and then tap the keyboard icon in the folder toolbar. If you select more than one PDF, the keyboard icon will be disabled as you can only rename one PDF at a time. Enter in a new name, or edit the existing one and tap the Done button.

40 |

Deleting PDFs

41 |

To permanently delete PDFs, tap the check mark symbol in a folder toolbar. Tap the PDFs that you wish to delete (a check mark will appear in the top right corner of each PDF thumbnail) and then tap the minus symbol in the folder toolbar. Tap Delete to confirm the deletion. To cancel PDF selection, tap the cross symbol in the folder toolbar.

42 |

Status Bar

43 |

By default, Viewer hides the status bar to enable full screen document viewing. To have Viewer show the status bar when viewing a document, press the home button and tap on Settings. Scroll down to Apps and tap on Viewer. Tap the ON switch to OFF.

44 | 45 | 46 | -------------------------------------------------------------------------------- /Sources/CGPDFDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // CGPDFDocument.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | #import 28 | 29 | // 30 | // Custom CGPDFDocument[...] functions 31 | // 32 | 33 | CGPDFDocumentRef CGPDFDocumentCreateUsingUrl(CFURLRef theURL, NSString *password); 34 | 35 | CGPDFDocumentRef CGPDFDocumentCreateUsingData(CGDataProviderRef dataProvider, NSString *password); 36 | 37 | BOOL CGPDFDocumentUrlNeedsPassword(CFURLRef theURL, NSString *password); 38 | 39 | BOOL CGPDFDocumentDataNeedsPassword(CGDataProviderRef dataProvider, NSString *password); 40 | -------------------------------------------------------------------------------- /Sources/CGPDFDocument.m: -------------------------------------------------------------------------------- 1 | // 2 | // CGPDFDocument.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "CGPDFDocument.h" 27 | 28 | // 29 | // CGPDFDocumentRef CGPDFDocumentCreateUsingUrl(CFURLRef, NSString *) function 30 | // 31 | 32 | CGPDFDocumentRef CGPDFDocumentCreateUsingUrl(CFURLRef theURL, NSString *password) 33 | { 34 | CGPDFDocumentRef thePDFDocRef = NULL; // CGPDFDocument 35 | 36 | if (theURL != NULL) // Check for non-NULL CFURLRef 37 | { 38 | thePDFDocRef = CGPDFDocumentCreateWithURL(theURL); 39 | 40 | if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef 41 | { 42 | if (CGPDFDocumentIsEncrypted(thePDFDocRef) == TRUE) // Encrypted 43 | { 44 | // Try a blank password first, per Apple's Quartz PDF example 45 | 46 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, "") == FALSE) 47 | { 48 | // Nope, now let's try the provided password to unlock the PDF 49 | 50 | if ((password != nil) && (password.length > 0)) // Not blank? 51 | { 52 | char text[128]; // char array buffer for the string conversion 53 | 54 | [password getCString:text maxLength:126 encoding:NSUTF8StringEncoding]; 55 | 56 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, text) == FALSE) // Log failure 57 | { 58 | #ifdef DEBUG 59 | NSLog(@"CGPDFDocumentCreateUsingUrl: Unable to unlock [%@] with [%@]", theURL, password); 60 | #endif 61 | } 62 | } 63 | } 64 | 65 | if (CGPDFDocumentIsUnlocked(thePDFDocRef) == FALSE) // Cleanup unlock failure 66 | { 67 | CGPDFDocumentRelease(thePDFDocRef), thePDFDocRef = NULL; 68 | } 69 | } 70 | } 71 | } 72 | else // Log an error diagnostic 73 | { 74 | #ifdef DEBUG 75 | NSLog(@"CGPDFDocumentCreateUsingUrl: theURL == NULL"); 76 | #endif 77 | } 78 | 79 | return thePDFDocRef; 80 | } 81 | 82 | // 83 | // CGPDFDocumentRef CGPDFDocumentCreateUsingData(CGDataProviderRef, NSString *) function 84 | // 85 | 86 | CGPDFDocumentRef CGPDFDocumentCreateUsingData(CGDataProviderRef dataProvider, NSString *password) 87 | { 88 | CGPDFDocumentRef thePDFDocRef = NULL; // CGPDFDocument 89 | 90 | if (dataProvider != NULL) // Check for non-NULL CGDataProviderRef 91 | { 92 | thePDFDocRef = CGPDFDocumentCreateWithProvider(dataProvider); 93 | 94 | if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef 95 | { 96 | if (CGPDFDocumentIsEncrypted(thePDFDocRef) == TRUE) // Encrypted 97 | { 98 | // Try a blank password first, per Apple's Quartz PDF example 99 | 100 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, "") == FALSE) 101 | { 102 | // Nope, now let's try the provided password to unlock the PDF 103 | 104 | if ((password != nil) && (password.length > 0)) // Not blank? 105 | { 106 | char text[128]; // char array buffer for the string conversion 107 | 108 | [password getCString:text maxLength:126 encoding:NSUTF8StringEncoding]; 109 | 110 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, text) == FALSE) // Log failure 111 | { 112 | #ifdef DEBUG 113 | NSLog(@"CGPDFDocumentCreateUsingData: Unable to unlock data with '%@'", password); 114 | #endif 115 | } 116 | } 117 | } 118 | 119 | if (CGPDFDocumentIsUnlocked(thePDFDocRef) == FALSE) // Cleanup unlock failure 120 | { 121 | CGPDFDocumentRelease(thePDFDocRef), thePDFDocRef = NULL; 122 | } 123 | } 124 | } 125 | } 126 | else // Log an error diagnostic 127 | { 128 | #ifdef DEBUG 129 | NSLog(@"CGPDFDocumentCreateUsingData: theURL == NULL"); 130 | #endif 131 | } 132 | 133 | return thePDFDocRef; 134 | } 135 | 136 | // 137 | // BOOL CGPDFDocumentUrlNeedsPassword(CFURLRef, NSString *) function 138 | // 139 | 140 | BOOL CGPDFDocumentUrlNeedsPassword(CFURLRef theURL, NSString *password) 141 | { 142 | BOOL needPassword = NO; // Default flag 143 | 144 | if (theURL != NULL) // Check for non-NULL CFURLRef 145 | { 146 | CGPDFDocumentRef thePDFDocRef = CGPDFDocumentCreateWithURL(theURL); 147 | 148 | if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef 149 | { 150 | if (CGPDFDocumentIsEncrypted(thePDFDocRef) == TRUE) // Encrypted 151 | { 152 | // Try a blank password first, per Apple's Quartz PDF example 153 | 154 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, "") == FALSE) 155 | { 156 | // Nope, now let's try the provided password to unlock the PDF 157 | 158 | if ((password != nil) && (password.length > 0)) // Not blank? 159 | { 160 | char text[128]; // char array buffer for the string conversion 161 | 162 | [password getCString:text maxLength:126 encoding:NSUTF8StringEncoding]; 163 | 164 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, text) == FALSE) 165 | { 166 | needPassword = YES; 167 | } 168 | } 169 | else 170 | { 171 | needPassword = YES; 172 | } 173 | } 174 | } 175 | 176 | CGPDFDocumentRelease(thePDFDocRef); // Cleanup CGPDFDocumentRef 177 | } 178 | } 179 | else // Log an error diagnostic 180 | { 181 | #ifdef DEBUG 182 | NSLog(@"CGPDFDocumentUrlNeedsPassword: theURL == NULL"); 183 | #endif 184 | } 185 | 186 | return needPassword; 187 | } 188 | 189 | // 190 | // BOOL CGPDFDocumentUrlNeedsPassword(CGDataProviderRef, NSString *) function 191 | // 192 | 193 | BOOL CGPDFDocumentDataNeedsPassword(CGDataProviderRef dataProvider, NSString *password) 194 | { 195 | BOOL needPassword = NO; // Default flag 196 | 197 | if (dataProvider != NULL) // Check for non-NULL CGDataProviderRef 198 | { 199 | CGPDFDocumentRef thePDFDocRef = CGPDFDocumentCreateWithProvider(dataProvider); 200 | 201 | if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef 202 | { 203 | if (CGPDFDocumentIsEncrypted(thePDFDocRef) == TRUE) // Encrypted 204 | { 205 | // Try a blank password first, per Apple's Quartz PDF example 206 | 207 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, "") == FALSE) 208 | { 209 | // Nope, now let's try the provided password to unlock the PDF 210 | 211 | if ((password != nil) && (password.length > 0)) // Not blank? 212 | { 213 | char text[128]; // char array buffer for the string conversion 214 | 215 | [password getCString:text maxLength:126 encoding:NSUTF8StringEncoding]; 216 | 217 | if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, text) == FALSE) 218 | { 219 | needPassword = YES; 220 | } 221 | } 222 | else 223 | { 224 | needPassword = YES; 225 | } 226 | } 227 | } 228 | 229 | CGPDFDocumentRelease(thePDFDocRef); // Cleanup CGPDFDocumentRef 230 | } 231 | } 232 | else // Log an error diagnostic 233 | { 234 | #ifdef DEBUG 235 | NSLog(@"CGPDFDocumentUrlNeedsPassword: theURL == NULL"); 236 | #endif 237 | } 238 | 239 | return needPassword; 240 | } 241 | 242 | // EOF 243 | -------------------------------------------------------------------------------- /Sources/ReaderContentPage.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderContentPage.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface ReaderContentPage : UIView 29 | 30 | - (instancetype)initWithURL:(NSURL *)fileURL page:(NSInteger)page password:(NSString *)phrase; 31 | 32 | - (id)processSingleTap:(UITapGestureRecognizer *)recognizer; 33 | 34 | @end 35 | 36 | #pragma mark - 37 | 38 | // 39 | // ReaderDocumentLink class interface 40 | // 41 | 42 | @interface ReaderDocumentLink : NSObject 43 | 44 | @property (nonatomic, assign, readonly) CGRect rect; 45 | 46 | @property (nonatomic, assign, readonly) CGPDFDictionaryRef dictionary; 47 | 48 | + (instancetype)newWithRect:(CGRect)linkRect dictionary:(CGPDFDictionaryRef)linkDictionary; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Sources/ReaderContentTile.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderContentTile.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | #import 28 | 29 | @interface ReaderContentTile : CATiledLayer 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Sources/ReaderContentTile.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderContentTile.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderContentTile.h" 27 | 28 | @implementation ReaderContentTile 29 | 30 | #pragma mark - Constants 31 | 32 | #define LEVELS_OF_DETAIL 16 33 | 34 | #pragma mark - ReaderContentTile class methods 35 | 36 | + (CFTimeInterval)fadeDuration 37 | { 38 | return 0.001; // iOS bug (flickering tiles) workaround 39 | } 40 | 41 | #pragma mark - ReaderContentTile instance methods 42 | 43 | - (instancetype)init 44 | { 45 | if ((self = [super init])) // Initialize superclass 46 | { 47 | self.levelsOfDetail = LEVELS_OF_DETAIL; // Zoom levels 48 | 49 | self.levelsOfDetailBias = (LEVELS_OF_DETAIL - 1); // Bias 50 | 51 | UIScreen *mainScreen = [UIScreen mainScreen]; // Main screen 52 | 53 | CGFloat screenScale = [mainScreen scale]; // Main screen scale 54 | 55 | CGRect screenBounds = [mainScreen bounds]; // Main screen bounds 56 | 57 | CGFloat w_pixels = (screenBounds.size.width * screenScale); 58 | 59 | CGFloat h_pixels = (screenBounds.size.height * screenScale); 60 | 61 | CGFloat max = ((w_pixels < h_pixels) ? h_pixels : w_pixels); 62 | 63 | CGFloat sizeOfTiles = ((max < 512.0f) ? 512.0f : 1024.0f); 64 | 65 | self.tileSize = CGSizeMake(sizeOfTiles, sizeOfTiles); 66 | } 67 | 68 | return self; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Sources/ReaderContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderContentView.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbView.h" 29 | 30 | @class ReaderContentView; 31 | @class ReaderContentPage; 32 | @class ReaderContentThumb; 33 | 34 | @protocol ReaderContentViewDelegate 35 | 36 | @required // Delegate protocols 37 | 38 | - (void)contentView:(ReaderContentView *)contentView touchesBegan:(NSSet *)touches; 39 | 40 | @end 41 | 42 | @interface ReaderContentView : UIScrollView 43 | 44 | @property (nonatomic, weak, readwrite) id message; 45 | 46 | - (instancetype)initWithFrame:(CGRect)frame fileURL:(NSURL *)fileURL page:(NSUInteger)page password:(NSString *)phrase; 47 | 48 | - (void)showPageThumb:(NSURL *)fileURL page:(NSInteger)page password:(NSString *)phrase guid:(NSString *)guid; 49 | 50 | - (id)processSingleTap:(UITapGestureRecognizer *)recognizer; 51 | 52 | - (void)zoomIncrement:(UITapGestureRecognizer *)recognizer; 53 | - (void)zoomDecrement:(UITapGestureRecognizer *)recognizer; 54 | - (void)zoomResetAnimated:(BOOL)animated; 55 | 56 | @end 57 | 58 | #pragma mark - 59 | 60 | // 61 | // ReaderContentThumb class interface 62 | // 63 | 64 | @interface ReaderContentThumb : ReaderThumbView 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /Sources/ReaderDocumentOutline.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderDocumentOutline.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface ReaderDocumentOutline : NSObject 29 | 30 | + (NSArray *)outlineFromFileURL:(NSURL *)fileURL password:(NSString *)phrase; 31 | 32 | + (void)logDocumentOutlineArray:(NSArray *)array; 33 | 34 | @end 35 | 36 | @interface DocumentOutlineEntry : NSObject 37 | 38 | + (instancetype)newWithTitle:(NSString *)title target:(id)target level:(NSInteger)level; 39 | 40 | @property (nonatomic, assign, readonly) NSInteger level; 41 | @property (nonatomic, strong, readwrite) NSMutableArray *children; 42 | @property (nonatomic, strong, readonly) NSString *title; 43 | @property (nonatomic, strong, readonly) id target; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Sources/ReaderMainPagebar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderMainPagebar.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbView.h" 29 | 30 | @class ReaderMainPagebar; 31 | @class ReaderTrackControl; 32 | @class ReaderPagebarThumb; 33 | @class ReaderDocument; 34 | 35 | @protocol ReaderMainPagebarDelegate 36 | 37 | @required // Delegate protocols 38 | 39 | - (void)pagebar:(ReaderMainPagebar *)pagebar gotoPage:(NSInteger)page; 40 | 41 | @end 42 | 43 | @interface ReaderMainPagebar : UIView 44 | 45 | @property (nonatomic, weak, readwrite) id delegate; 46 | 47 | - (instancetype)initWithFrame:(CGRect)frame document:(ReaderDocument *)object; 48 | 49 | - (void)updatePagebar; 50 | 51 | - (void)hidePagebar; 52 | - (void)showPagebar; 53 | 54 | @end 55 | 56 | #pragma mark - 57 | 58 | // 59 | // ReaderTrackControl class interface 60 | // 61 | 62 | @interface ReaderTrackControl : UIControl 63 | 64 | @property (nonatomic, assign, readonly) CGFloat value; 65 | 66 | @end 67 | 68 | #pragma mark - 69 | 70 | // 71 | // ReaderPagebarThumb class interface 72 | // 73 | 74 | @interface ReaderPagebarThumb : ReaderThumbView 75 | 76 | - (instancetype)initWithFrame:(CGRect)frame small:(BOOL)small; 77 | 78 | @end 79 | 80 | #pragma mark - 81 | 82 | // 83 | // ReaderPagebarShadow class interface 84 | // 85 | 86 | @interface ReaderPagebarShadow : UIView 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Sources/ReaderMainToolbar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderMainToolbar.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "UIXToolbarView.h" 29 | 30 | @class ReaderMainToolbar; 31 | @class ReaderDocument; 32 | 33 | @protocol ReaderMainToolbarDelegate 34 | 35 | @required // Delegate protocols 36 | 37 | - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar doneButton:(UIButton *)button; 38 | - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar thumbsButton:(UIButton *)button; 39 | - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar exportButton:(UIButton *)button; 40 | - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar printButton:(UIButton *)button; 41 | - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar emailButton:(UIButton *)button; 42 | - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar markButton:(UIButton *)button; 43 | 44 | @end 45 | 46 | @interface ReaderMainToolbar : UIXToolbarView 47 | 48 | @property (nonatomic, weak, readwrite) id delegate; 49 | 50 | - (instancetype)initWithFrame:(CGRect)frame document:(ReaderDocument *)document; 51 | 52 | - (void)setBookmarkState:(BOOL)state; 53 | 54 | - (void)hideToolbar; 55 | - (void)showToolbar; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Sources/ReaderThumbCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbCache.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbRequest.h" 29 | 30 | @interface ReaderThumbCache : NSObject 31 | 32 | + (ReaderThumbCache *)sharedInstance; 33 | 34 | + (void)touchThumbCacheWithGUID:(NSString *)guid; 35 | 36 | + (void)createThumbCacheWithGUID:(NSString *)guid; 37 | 38 | + (void)removeThumbCacheWithGUID:(NSString *)guid; 39 | 40 | + (void)purgeThumbCachesOlderThan:(NSTimeInterval)age; 41 | 42 | + (NSString *)thumbCachePathForGUID:(NSString *)guid; 43 | 44 | - (id)thumbRequest:(ReaderThumbRequest *)request priority:(BOOL)priority; 45 | 46 | - (void)setObject:(UIImage *)image forKey:(NSString *)key; 47 | 48 | - (void)removeObjectForKey:(NSString *)key; 49 | 50 | - (void)removeNullForKey:(NSString *)key; 51 | 52 | - (void)removeAllObjects; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Sources/ReaderThumbCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbCache.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderThumbCache.h" 27 | #import "ReaderThumbQueue.h" 28 | #import "ReaderThumbFetch.h" 29 | #import "ReaderThumbView.h" 30 | 31 | @implementation ReaderThumbCache 32 | { 33 | NSCache *thumbCache; 34 | } 35 | 36 | #pragma mark - Constants 37 | 38 | #define CACHE_SIZE 2097152 39 | 40 | #pragma mark - ReaderThumbCache class methods 41 | 42 | + (ReaderThumbCache *)sharedInstance 43 | { 44 | static dispatch_once_t predicate = 0; 45 | 46 | static ReaderThumbCache *object = nil; // Object 47 | 48 | dispatch_once(&predicate, ^{ object = [self new]; }); 49 | 50 | return object; // ReaderThumbCache singleton 51 | } 52 | 53 | + (NSString *)appCachesPath 54 | { 55 | static dispatch_once_t predicate = 0; 56 | 57 | static NSString *theCachesPath = nil; // Application caches path string 58 | 59 | dispatch_once(&predicate, // Save a copy of the application caches path the first time it is needed 60 | ^{ 61 | NSArray *cachesPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 62 | 63 | theCachesPath = [[cachesPaths objectAtIndex:0] copy]; // Keep a copy for later abusage 64 | }); 65 | 66 | return theCachesPath; 67 | } 68 | 69 | + (NSString *)thumbCachePathForGUID:(NSString *)guid 70 | { 71 | NSString *cachesPath = [ReaderThumbCache appCachesPath]; // Caches path 72 | 73 | return [cachesPath stringByAppendingPathComponent:guid]; // Append GUID 74 | } 75 | 76 | + (void)createThumbCacheWithGUID:(NSString *)guid 77 | { 78 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 79 | 80 | NSString *cachePath = [ReaderThumbCache thumbCachePathForGUID:guid]; // Thumb cache path 81 | 82 | [fileManager createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:NULL]; 83 | } 84 | 85 | + (void)removeThumbCacheWithGUID:(NSString *)guid 86 | { 87 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), 88 | ^{ 89 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 90 | 91 | NSString *cachePath = [ReaderThumbCache thumbCachePathForGUID:guid]; // Thumb cache path 92 | 93 | [fileManager removeItemAtPath:cachePath error:NULL]; // Remove thumb cache directory 94 | }); 95 | } 96 | 97 | + (void)touchThumbCacheWithGUID:(NSString *)guid 98 | { 99 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 100 | 101 | NSString *cachePath = [ReaderThumbCache thumbCachePathForGUID:guid]; // Thumb cache path 102 | 103 | NSDictionary *attributes = [NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate]; 104 | 105 | [fileManager setAttributes:attributes ofItemAtPath:cachePath error:NULL]; // New modification date 106 | } 107 | 108 | + (void)purgeThumbCachesOlderThan:(NSTimeInterval)age 109 | { 110 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), 111 | ^{ 112 | NSDate *now = [NSDate date]; // Right about now time 113 | 114 | NSString *cachesPath = [ReaderThumbCache appCachesPath]; // Caches path 115 | 116 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 117 | 118 | NSArray *cachesList = [fileManager contentsOfDirectoryAtPath:cachesPath error:NULL]; 119 | 120 | if (cachesList != nil) // Process caches directory contents 121 | { 122 | for (NSString *cacheName in cachesList) // Enumerate directory contents 123 | { 124 | if (cacheName.length == 36) // This is a very hacky cache ident kludge 125 | { 126 | NSString *cachePath = [cachesPath stringByAppendingPathComponent:cacheName]; 127 | 128 | NSDictionary *attributes = [fileManager attributesOfItemAtPath:cachePath error:NULL]; 129 | 130 | NSDate *cacheDate = [attributes objectForKey:NSFileModificationDate]; // Cache date 131 | 132 | NSTimeInterval seconds = [now timeIntervalSinceDate:cacheDate]; // Cache age 133 | 134 | if (seconds > age) // Older than so remove the thumb cache 135 | { 136 | [fileManager removeItemAtPath:cachePath error:NULL]; 137 | 138 | #ifdef DEBUG 139 | NSLog(@"%s purged %@", __FUNCTION__, cacheName); 140 | #endif 141 | } 142 | } 143 | } 144 | } 145 | }); 146 | } 147 | 148 | #pragma mark - ReaderThumbCache instance methods 149 | 150 | - (instancetype)init 151 | { 152 | if ((self = [super init])) // Initialize 153 | { 154 | thumbCache = [NSCache new]; // Cache 155 | 156 | [thumbCache setName:@"ReaderThumbCache"]; 157 | 158 | [thumbCache setTotalCostLimit:CACHE_SIZE]; 159 | } 160 | 161 | return self; 162 | } 163 | 164 | - (id)thumbRequest:(ReaderThumbRequest *)request priority:(BOOL)priority 165 | { 166 | @synchronized(thumbCache) // Mutex lock 167 | { 168 | id object = [thumbCache objectForKey:request.cacheKey]; 169 | 170 | if (object == nil) // Thumb object does not yet exist in the cache 171 | { 172 | object = [NSNull null]; // Return an NSNull thumb placeholder object 173 | 174 | [thumbCache setObject:object forKey:request.cacheKey cost:2]; // Cache the placeholder object 175 | 176 | ReaderThumbFetch *thumbFetch = [[ReaderThumbFetch alloc] initWithRequest:request]; // Create a thumb fetch operation 177 | 178 | [thumbFetch setQueuePriority:(priority ? NSOperationQueuePriorityNormal : NSOperationQueuePriorityLow)]; // Queue priority 179 | 180 | request.thumbView.operation = thumbFetch; [thumbFetch setThreadPriority:(priority ? 0.55 : 0.35)]; // Thread priority 181 | 182 | [[ReaderThumbQueue sharedInstance] addLoadOperation:thumbFetch]; // Queue the operation 183 | } 184 | 185 | return object; // NSNull or UIImage 186 | } 187 | } 188 | 189 | - (void)setObject:(UIImage *)image forKey:(NSString *)key 190 | { 191 | @synchronized(thumbCache) // Mutex lock 192 | { 193 | NSUInteger bytes = (image.size.width * image.size.height * 4.0f); 194 | 195 | [thumbCache setObject:image forKey:key cost:bytes]; // Cache image 196 | } 197 | } 198 | 199 | - (void)removeObjectForKey:(NSString *)key 200 | { 201 | @synchronized(thumbCache) // Mutex lock 202 | { 203 | [thumbCache removeObjectForKey:key]; 204 | } 205 | } 206 | 207 | - (void)removeNullForKey:(NSString *)key 208 | { 209 | @synchronized(thumbCache) // Mutex lock 210 | { 211 | id object = [thumbCache objectForKey:key]; 212 | 213 | if ([object isMemberOfClass:[NSNull class]]) 214 | { 215 | [thumbCache removeObjectForKey:key]; 216 | } 217 | } 218 | } 219 | 220 | - (void)removeAllObjects 221 | { 222 | @synchronized(thumbCache) // Mutex lock 223 | { 224 | [thumbCache removeAllObjects]; 225 | } 226 | } 227 | 228 | @end 229 | -------------------------------------------------------------------------------- /Sources/ReaderThumbFetch.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbFetch.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbQueue.h" 29 | 30 | @class ReaderThumbRequest; 31 | 32 | @interface ReaderThumbFetch : ReaderThumbOperation 33 | 34 | - (instancetype)initWithRequest:(ReaderThumbRequest *)options; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Sources/ReaderThumbFetch.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbFetch.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderThumbFetch.h" 27 | #import "ReaderThumbRender.h" 28 | #import "ReaderThumbCache.h" 29 | #import "ReaderThumbView.h" 30 | 31 | #import 32 | 33 | @implementation ReaderThumbFetch 34 | { 35 | ReaderThumbRequest *request; 36 | } 37 | 38 | #pragma mark - ReaderThumbFetch instance methods 39 | 40 | - (instancetype)initWithRequest:(ReaderThumbRequest *)options 41 | { 42 | if ((self = [super initWithGUID:options.guid])) 43 | { 44 | request = options; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (void)cancel 51 | { 52 | [super cancel]; // Cancel the operation 53 | 54 | request.thumbView.operation = nil; // Break retain loop 55 | 56 | request.thumbView = nil; // Release target thumb view on cancel 57 | 58 | [[ReaderThumbCache sharedInstance] removeNullForKey:request.cacheKey]; 59 | } 60 | 61 | - (NSURL *)thumbFileURL 62 | { 63 | NSString *cachePath = [ReaderThumbCache thumbCachePathForGUID:request.guid]; // Thumb cache path 64 | 65 | NSString *fileName = [[NSString alloc] initWithFormat:@"%@.png", request.thumbName]; // Thumb file name 66 | 67 | return [NSURL fileURLWithPath:[cachePath stringByAppendingPathComponent:fileName]]; // File URL 68 | } 69 | 70 | - (void)main 71 | { 72 | CGImageRef imageRef = NULL; NSURL *thumbURL = [self thumbFileURL]; 73 | 74 | CGImageSourceRef loadRef = CGImageSourceCreateWithURL((__bridge CFURLRef)thumbURL, NULL); 75 | 76 | if (loadRef != NULL) // Load the existing thumb image 77 | { 78 | imageRef = CGImageSourceCreateImageAtIndex(loadRef, 0, NULL); // Load it 79 | 80 | CFRelease(loadRef); // Release CGImageSource reference 81 | } 82 | else // Existing thumb image not found - so create and queue up a thumb render operation on the work queue 83 | { 84 | ReaderThumbRender *thumbRender = [[ReaderThumbRender alloc] initWithRequest:request]; // Create a thumb render operation 85 | 86 | [thumbRender setQueuePriority:self.queuePriority]; [thumbRender setThreadPriority:(self.threadPriority - 0.1)]; // Priority 87 | 88 | if (self.isCancelled == NO) // We're not cancelled - so update things and add the render operation to the work queue 89 | { 90 | request.thumbView.operation = thumbRender; // Update the thumb view operation property to the new operation 91 | 92 | [[ReaderThumbQueue sharedInstance] addWorkOperation:thumbRender]; return; // Queue the operation 93 | } 94 | } 95 | 96 | if (imageRef != NULL) // Create a UIImage from a CGImage and show it 97 | { 98 | UIImage *image = [UIImage imageWithCGImage:imageRef scale:request.scale orientation:UIImageOrientationUp]; 99 | 100 | CGImageRelease(imageRef); // Release the CGImage reference from the above thumb load code 101 | 102 | UIGraphicsBeginImageContextWithOptions(image.size, YES, request.scale); // Graphics context 103 | 104 | [image drawAtPoint:CGPointZero]; // Decode and draw the image on this background thread 105 | 106 | UIImage *decoded = UIGraphicsGetImageFromCurrentImageContext(); // Newly decoded image 107 | 108 | UIGraphicsEndImageContext(); // Cleanup after the bitmap-based graphics drawing context 109 | 110 | [[ReaderThumbCache sharedInstance] setObject:decoded forKey:request.cacheKey]; // Cache it 111 | 112 | if (self.isCancelled == NO) // Show the image in the target thumb view on the main thread 113 | { 114 | ReaderThumbView *thumbView = request.thumbView; // Target thumb view for image show 115 | 116 | NSUInteger targetTag = request.targetTag; // Target reference tag for image show 117 | 118 | dispatch_async(dispatch_get_main_queue(), // Queue image show on main thread 119 | ^{ 120 | if (thumbView.targetTag == targetTag) [thumbView showImage:decoded]; 121 | }); 122 | } 123 | } 124 | 125 | request.thumbView.operation = nil; // Break retain loop 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /Sources/ReaderThumbQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbQueue.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface ReaderThumbQueue : NSObject 29 | 30 | + (ReaderThumbQueue *)sharedInstance; 31 | 32 | - (void)addLoadOperation:(NSOperation *)operation; 33 | 34 | - (void)addWorkOperation:(NSOperation *)operation; 35 | 36 | - (void)cancelOperationsWithGUID:(NSString *)guid; 37 | 38 | - (void)cancelAllOperations; 39 | 40 | @end 41 | 42 | #pragma mark - 43 | 44 | // 45 | // ReaderThumbOperation class interface 46 | // 47 | 48 | @interface ReaderThumbOperation : NSOperation 49 | 50 | @property (nonatomic, strong, readonly) NSString *guid; 51 | 52 | - (instancetype)initWithGUID:(NSString *)guid; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Sources/ReaderThumbQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbQueue.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderThumbQueue.h" 27 | 28 | @implementation ReaderThumbQueue 29 | { 30 | NSOperationQueue *loadQueue; 31 | 32 | NSOperationQueue *workQueue; 33 | } 34 | 35 | #pragma mark - ReaderThumbQueue class methods 36 | 37 | + (ReaderThumbQueue *)sharedInstance 38 | { 39 | static dispatch_once_t predicate = 0; 40 | 41 | static ReaderThumbQueue *object = nil; // Object 42 | 43 | dispatch_once(&predicate, ^{ object = [self new]; }); 44 | 45 | return object; // ReaderThumbQueue singleton 46 | } 47 | 48 | #pragma mark - ReaderThumbQueue instance methods 49 | 50 | - (instancetype)init 51 | { 52 | if ((self = [super init])) // Initialize 53 | { 54 | loadQueue = [NSOperationQueue new]; 55 | 56 | [loadQueue setName:@"ReaderThumbLoadQueue"]; 57 | 58 | [loadQueue setMaxConcurrentOperationCount:1]; 59 | 60 | workQueue = [NSOperationQueue new]; 61 | 62 | [workQueue setName:@"ReaderThumbWorkQueue"]; 63 | 64 | [workQueue setMaxConcurrentOperationCount:1]; 65 | } 66 | 67 | return self; 68 | } 69 | 70 | - (void)addLoadOperation:(NSOperation *)operation 71 | { 72 | if ([operation isKindOfClass:[ReaderThumbOperation class]]) 73 | { 74 | [loadQueue addOperation:operation]; // Add to load queue 75 | } 76 | } 77 | 78 | - (void)addWorkOperation:(NSOperation *)operation 79 | { 80 | if ([operation isKindOfClass:[ReaderThumbOperation class]]) 81 | { 82 | [workQueue addOperation:operation]; // Add to work queue 83 | } 84 | } 85 | 86 | - (void)cancelOperationsWithGUID:(NSString *)guid 87 | { 88 | [loadQueue setSuspended:YES]; [workQueue setSuspended:YES]; 89 | 90 | for (ReaderThumbOperation *operation in loadQueue.operations) 91 | { 92 | if ([operation isKindOfClass:[ReaderThumbOperation class]]) 93 | { 94 | if ([operation.guid isEqualToString:guid]) [operation cancel]; 95 | } 96 | } 97 | 98 | for (ReaderThumbOperation *operation in workQueue.operations) 99 | { 100 | if ([operation isKindOfClass:[ReaderThumbOperation class]]) 101 | { 102 | if ([operation.guid isEqualToString:guid]) [operation cancel]; 103 | } 104 | } 105 | 106 | [workQueue setSuspended:NO]; [loadQueue setSuspended:NO]; 107 | } 108 | 109 | - (void)cancelAllOperations 110 | { 111 | [loadQueue cancelAllOperations]; [workQueue cancelAllOperations]; 112 | } 113 | 114 | @end 115 | 116 | #pragma mark - 117 | 118 | // 119 | // ReaderThumbOperation class implementation 120 | // 121 | 122 | @implementation ReaderThumbOperation 123 | { 124 | NSString *_guid; 125 | } 126 | 127 | @synthesize guid = _guid; 128 | 129 | #pragma mark - ReaderThumbOperation instance methods 130 | 131 | - (instancetype)initWithGUID:(NSString *)guid 132 | { 133 | if ((self = [super init])) 134 | { 135 | _guid = guid; 136 | } 137 | 138 | return self; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Sources/ReaderThumbRender.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbRender.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbQueue.h" 29 | 30 | @class ReaderThumbRequest; 31 | 32 | @interface ReaderThumbRender : ReaderThumbOperation 33 | 34 | - (instancetype)initWithRequest:(ReaderThumbRequest *)options; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Sources/ReaderThumbRender.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbRender.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderThumbRender.h" 27 | #import "ReaderThumbCache.h" 28 | #import "ReaderThumbView.h" 29 | #import "CGPDFDocument.h" 30 | 31 | #import 32 | 33 | @implementation ReaderThumbRender 34 | { 35 | ReaderThumbRequest *request; 36 | } 37 | 38 | #pragma mark - ReaderThumbRender instance methods 39 | 40 | - (instancetype)initWithRequest:(ReaderThumbRequest *)options 41 | { 42 | if ((self = [super initWithGUID:options.guid])) 43 | { 44 | request = options; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (void)cancel 51 | { 52 | [super cancel]; // Cancel the operation 53 | 54 | request.thumbView.operation = nil; // Break retain loop 55 | 56 | request.thumbView = nil; // Release target thumb view on cancel 57 | 58 | [[ReaderThumbCache sharedInstance] removeNullForKey:request.cacheKey]; 59 | } 60 | 61 | - (NSURL *)thumbFileURL 62 | { 63 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 64 | 65 | NSString *cachePath = [ReaderThumbCache thumbCachePathForGUID:request.guid]; // Thumb cache path 66 | 67 | [fileManager createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:NULL]; 68 | 69 | NSString *fileName = [[NSString alloc] initWithFormat:@"%@.png", request.thumbName]; // Thumb file name 70 | 71 | return [NSURL fileURLWithPath:[cachePath stringByAppendingPathComponent:fileName]]; // File URL 72 | } 73 | 74 | - (void)main 75 | { 76 | NSInteger page = request.thumbPage; NSString *password = request.password; 77 | 78 | CGImageRef imageRef = NULL; CFURLRef fileURL = (__bridge CFURLRef)request.fileURL; 79 | 80 | CGPDFDocumentRef thePDFDocRef = CGPDFDocumentCreateUsingUrl(fileURL, password); 81 | 82 | if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef 83 | { 84 | CGPDFPageRef thePDFPageRef = CGPDFDocumentGetPage(thePDFDocRef, page); 85 | 86 | if (thePDFPageRef != NULL) // Check for non-NULL CGPDFPageRef 87 | { 88 | CGFloat thumb_w = request.thumbSize.width; // Maximum thumb width 89 | CGFloat thumb_h = request.thumbSize.height; // Maximum thumb height 90 | 91 | CGRect cropBoxRect = CGPDFPageGetBoxRect(thePDFPageRef, kCGPDFCropBox); 92 | CGRect mediaBoxRect = CGPDFPageGetBoxRect(thePDFPageRef, kCGPDFMediaBox); 93 | CGRect effectiveRect = CGRectIntersection(cropBoxRect, mediaBoxRect); 94 | 95 | NSInteger pageRotate = CGPDFPageGetRotationAngle(thePDFPageRef); // Angle 96 | 97 | CGFloat page_w = 0.0f; CGFloat page_h = 0.0f; // Rotated page size 98 | 99 | switch (pageRotate) // Page rotation (in degrees) 100 | { 101 | default: // Default case 102 | case 0: case 180: // 0 and 180 degrees 103 | { 104 | page_w = effectiveRect.size.width; 105 | page_h = effectiveRect.size.height; 106 | break; 107 | } 108 | 109 | case 90: case 270: // 90 and 270 degrees 110 | { 111 | page_h = effectiveRect.size.width; 112 | page_w = effectiveRect.size.height; 113 | break; 114 | } 115 | } 116 | 117 | CGFloat scale_w = (thumb_w / page_w); // Width scale 118 | CGFloat scale_h = (thumb_h / page_h); // Height scale 119 | 120 | CGFloat scale = 0.0f; // Page to target thumb size scale 121 | 122 | if (page_h > page_w) 123 | scale = ((thumb_h > thumb_w) ? scale_w : scale_h); // Portrait 124 | else 125 | scale = ((thumb_h < thumb_w) ? scale_h : scale_w); // Landscape 126 | 127 | NSInteger target_w = (page_w * scale); // Integer target thumb width 128 | NSInteger target_h = (page_h * scale); // Integer target thumb height 129 | 130 | if (target_w % 2) target_w--; if (target_h % 2) target_h--; // Even 131 | 132 | target_w *= request.scale; target_h *= request.scale; // Screen scale 133 | 134 | CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); // RGB color space 135 | 136 | CGBitmapInfo bmi = (kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); 137 | 138 | CGContextRef context = CGBitmapContextCreate(NULL, target_w, target_h, 8, 0, rgb, bmi); 139 | 140 | if (context != NULL) // Must have a valid custom CGBitmap context to draw into 141 | { 142 | CGRect thumbRect = CGRectMake(0.0f, 0.0f, target_w, target_h); // Target thumb rect 143 | 144 | CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); CGContextFillRect(context, thumbRect); // White fill 145 | 146 | CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(thePDFPageRef, kCGPDFCropBox, thumbRect, 0, true)); // Fit rect 147 | 148 | //CGContextSetRenderingIntent(context, kCGRenderingIntentDefault); CGContextSetInterpolationQuality(context, kCGInterpolationDefault); 149 | 150 | CGContextDrawPDFPage(context, thePDFPageRef); // Render the PDF page into the custom CGBitmap context 151 | 152 | imageRef = CGBitmapContextCreateImage(context); // Create CGImage from custom CGBitmap context 153 | 154 | CGContextRelease(context); // Release custom CGBitmap context reference 155 | } 156 | 157 | CGColorSpaceRelease(rgb); // Release device RGB color space reference 158 | } 159 | 160 | CGPDFDocumentRelease(thePDFDocRef); // Release CGPDFDocumentRef reference 161 | } 162 | 163 | if (imageRef != NULL) // Create UIImage from CGImage and show it, then save thumb as PNG 164 | { 165 | UIImage *image = [UIImage imageWithCGImage:imageRef scale:request.scale orientation:UIImageOrientationUp]; 166 | 167 | [[ReaderThumbCache sharedInstance] setObject:image forKey:request.cacheKey]; // Update cache 168 | 169 | if (self.isCancelled == NO) // Show the image in the target thumb view on the main thread 170 | { 171 | ReaderThumbView *thumbView = request.thumbView; // Target thumb view for image show 172 | 173 | NSUInteger targetTag = request.targetTag; // Target reference tag for image show 174 | 175 | dispatch_async(dispatch_get_main_queue(), // Queue image show on main thread 176 | ^{ 177 | if (thumbView.targetTag == targetTag) [thumbView showImage:image]; 178 | }); 179 | } 180 | 181 | CFURLRef thumbURL = (__bridge CFURLRef)[self thumbFileURL]; // Thumb cache path with PNG file name URL 182 | 183 | CGImageDestinationRef thumbRef = CGImageDestinationCreateWithURL(thumbURL, (CFStringRef)@"public.png", 1, NULL); 184 | 185 | if (thumbRef != NULL) // Write the thumb image file out to the thumb cache directory 186 | { 187 | CGImageDestinationAddImage(thumbRef, imageRef, NULL); // Add the image 188 | 189 | CGImageDestinationFinalize(thumbRef); // Finalize the image file 190 | 191 | CFRelease(thumbRef); // Release CGImageDestination reference 192 | } 193 | 194 | CGImageRelease(imageRef); // Release CGImage reference 195 | } 196 | else // No image - so remove the placeholder object from the cache 197 | { 198 | [[ReaderThumbCache sharedInstance] removeNullForKey:request.cacheKey]; 199 | } 200 | 201 | request.thumbView.operation = nil; // Break retain loop 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /Sources/ReaderThumbRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbRequest.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @class ReaderThumbView; 29 | 30 | @interface ReaderThumbRequest : NSObject 31 | 32 | @property (nonatomic, strong, readonly) NSURL *fileURL; 33 | @property (nonatomic, strong, readonly) NSString *guid; 34 | @property (nonatomic, strong, readonly) NSString *password; 35 | @property (nonatomic, strong, readonly) NSString *cacheKey; 36 | @property (nonatomic, strong, readonly) NSString *thumbName; 37 | @property (nonatomic, strong, readwrite) ReaderThumbView *thumbView; 38 | @property (nonatomic, assign, readonly) NSUInteger targetTag; 39 | @property (nonatomic, assign, readonly) NSInteger thumbPage; 40 | @property (nonatomic, assign, readonly) CGSize thumbSize; 41 | @property (nonatomic, assign, readonly) CGFloat scale; 42 | 43 | + (instancetype)newForView:(ReaderThumbView *)view fileURL:(NSURL *)url password:(NSString *)phrase guid:(NSString *)guid page:(NSInteger)page size:(CGSize)size; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Sources/ReaderThumbRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbRequest.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderThumbRequest.h" 27 | #import "ReaderThumbView.h" 28 | 29 | @implementation ReaderThumbRequest 30 | { 31 | NSURL *_fileURL; 32 | 33 | NSString *_guid; 34 | 35 | NSString *_password; 36 | 37 | NSString *_cacheKey; 38 | 39 | NSString *_thumbName; 40 | 41 | ReaderThumbView *_thumbView; 42 | 43 | NSUInteger _targetTag; 44 | 45 | NSInteger _thumbPage; 46 | 47 | CGSize _thumbSize; 48 | 49 | CGFloat _scale; 50 | } 51 | 52 | #pragma mark - Properties 53 | 54 | @synthesize guid = _guid; 55 | @synthesize fileURL = _fileURL; 56 | @synthesize password = _password; 57 | @synthesize thumbView = _thumbView; 58 | @synthesize thumbPage = _thumbPage; 59 | @synthesize thumbSize = _thumbSize; 60 | @synthesize thumbName = _thumbName; 61 | @synthesize targetTag = _targetTag; 62 | @synthesize cacheKey = _cacheKey; 63 | @synthesize scale = _scale; 64 | 65 | #pragma mark - ReaderThumbRequest class methods 66 | 67 | + (instancetype)newForView:(ReaderThumbView *)view fileURL:(NSURL *)url password:(NSString *)phrase guid:(NSString *)guid page:(NSInteger)page size:(CGSize)size 68 | { 69 | return [[ReaderThumbRequest alloc] initForView:view fileURL:url password:phrase guid:guid page:page size:size]; 70 | } 71 | 72 | #pragma mark - ReaderThumbRequest instance methods 73 | 74 | - (instancetype)initForView:(ReaderThumbView *)view fileURL:(NSURL *)url password:(NSString *)phrase guid:(NSString *)guid page:(NSInteger)page size:(CGSize)size 75 | { 76 | if ((self = [super init])) // Initialize object 77 | { 78 | NSInteger w = size.width; NSInteger h = size.height; 79 | 80 | _thumbView = view; _thumbPage = page; _thumbSize = size; 81 | 82 | _fileURL = [url copy]; _password = [phrase copy]; _guid = [guid copy]; 83 | 84 | _thumbName = [[NSString alloc] initWithFormat:@"%07i-%04ix%04i", (int)page, (int)w, (int)h]; 85 | 86 | _cacheKey = [[NSString alloc] initWithFormat:@"%@+%@", _thumbName, _guid]; 87 | 88 | _targetTag = [_cacheKey hash]; _thumbView.targetTag = _targetTag; 89 | 90 | _scale = [[UIScreen mainScreen] scale]; // Thumb screen scale 91 | } 92 | 93 | return self; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /Sources/ReaderThumbView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbView.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface ReaderThumbView : UIView 29 | { 30 | @protected // Instance variables 31 | 32 | UIImageView *imageView; 33 | } 34 | 35 | @property (atomic, strong, readwrite) NSOperation *operation; 36 | 37 | @property (nonatomic, assign, readwrite) NSUInteger targetTag; 38 | 39 | - (void)showImage:(UIImage *)image; 40 | 41 | - (void)showTouched:(BOOL)touched; 42 | 43 | - (void)reuse; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Sources/ReaderThumbView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbView.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderThumbView.h" 27 | 28 | @implementation ReaderThumbView 29 | { 30 | NSOperation *_operation; 31 | 32 | NSUInteger _targetTag; 33 | } 34 | 35 | #pragma mark - Properties 36 | 37 | @synthesize operation = _operation; 38 | @synthesize targetTag = _targetTag; 39 | 40 | #pragma mark - ReaderThumbView instance methods 41 | 42 | - (instancetype)initWithFrame:(CGRect)frame 43 | { 44 | if ((self = [super initWithFrame:frame])) 45 | { 46 | self.autoresizesSubviews = NO; 47 | self.userInteractionEnabled = NO; 48 | self.contentMode = UIViewContentModeRedraw; 49 | self.autoresizingMask = UIViewAutoresizingNone; 50 | self.backgroundColor = [UIColor clearColor]; 51 | 52 | imageView = [[UIImageView alloc] initWithFrame:self.bounds]; 53 | 54 | imageView.autoresizesSubviews = NO; 55 | imageView.userInteractionEnabled = NO; 56 | imageView.autoresizingMask = UIViewAutoresizingNone; 57 | imageView.contentMode = UIViewContentModeScaleAspectFit; 58 | 59 | [self addSubview:imageView]; 60 | } 61 | 62 | return self; 63 | } 64 | 65 | - (void)showImage:(UIImage *)image 66 | { 67 | imageView.image = image; // Show image 68 | } 69 | 70 | - (void)showTouched:(BOOL)touched 71 | { 72 | // Implemented by ReaderThumbView subclass 73 | } 74 | 75 | - (void)removeFromSuperview 76 | { 77 | _targetTag = 0; // Clear target tag 78 | 79 | [self.operation cancel]; // Cancel operation 80 | 81 | [super removeFromSuperview]; // Remove view 82 | } 83 | 84 | - (void)reuse 85 | { 86 | _targetTag = 0; // Clear target tag 87 | 88 | [self.operation cancel]; // Cancel operation 89 | 90 | imageView.image = nil; // Release image 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Sources/ReaderThumbsView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderThumbsView.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderThumbView.h" 29 | 30 | @class ReaderThumbsView; 31 | 32 | @protocol ReaderThumbsViewDelegate 33 | 34 | @required // Delegate protocols 35 | 36 | - (NSUInteger)numberOfThumbsInThumbsView:(ReaderThumbsView *)thumbsView; 37 | 38 | - (id)thumbsView:(ReaderThumbsView *)thumbsView thumbCellWithFrame:(CGRect)frame; 39 | 40 | - (void)thumbsView:(ReaderThumbsView *)thumbsView updateThumbCell:(id)thumbCell forIndex:(NSInteger)index; 41 | 42 | - (void)thumbsView:(ReaderThumbsView *)thumbsView didSelectThumbWithIndex:(NSInteger)index; 43 | 44 | @optional // Delegate protocols 45 | 46 | - (void)thumbsView:(ReaderThumbsView *)thumbsView refreshThumbCell:(id)thumbCell forIndex:(NSInteger)index; 47 | 48 | - (void)thumbsView:(ReaderThumbsView *)thumbsView didPressThumbWithIndex:(NSInteger)index; 49 | 50 | @end 51 | 52 | @interface ReaderThumbsView : UIScrollView 53 | 54 | @property (nonatomic, weak, readwrite) id delegate; 55 | 56 | - (void)setThumbSize:(CGSize)thumbSize; 57 | 58 | - (void)reloadThumbsCenterOnIndex:(NSInteger)index; 59 | 60 | - (void)reloadThumbsContentOffset:(CGPoint)newContentOffset; 61 | 62 | - (void)refreshThumbWithIndex:(NSInteger)index; 63 | 64 | - (void)refreshVisibleThumbs; 65 | 66 | - (CGPoint)insetContentOffset; 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Sources/ReaderViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderViewController.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-07-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ReaderDocument.h" 29 | 30 | @class ReaderViewController; 31 | 32 | @protocol ReaderViewControllerDelegate 33 | 34 | @optional // Delegate protocols 35 | 36 | - (void)dismissReaderViewController:(ReaderViewController *)viewController; 37 | 38 | @end 39 | 40 | @interface ReaderViewController : UIViewController 41 | 42 | @property (nonatomic, weak, readwrite) id delegate; 43 | 44 | - (instancetype)initWithReaderDocument:(ReaderDocument *)object; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Sources/ThumbsMainToolbar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbsMainToolbar.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "UIXToolbarView.h" 29 | 30 | @class ThumbsMainToolbar; 31 | 32 | @protocol ThumbsMainToolbarDelegate 33 | 34 | @required // Delegate protocols 35 | 36 | - (void)tappedInToolbar:(ThumbsMainToolbar *)toolbar doneButton:(UIButton *)button; 37 | - (void)tappedInToolbar:(ThumbsMainToolbar *)toolbar showControl:(UISegmentedControl *)control; 38 | 39 | @end 40 | 41 | @interface ThumbsMainToolbar : UIXToolbarView 42 | 43 | @property (nonatomic, weak, readwrite) id delegate; 44 | 45 | - (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Sources/ThumbsMainToolbar.m: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbsMainToolbar.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderConstants.h" 27 | #import "ThumbsMainToolbar.h" 28 | 29 | @implementation ThumbsMainToolbar 30 | 31 | #pragma mark - Constants 32 | 33 | #define BUTTON_X 8.0f 34 | #define BUTTON_Y 8.0f 35 | 36 | #define BUTTON_SPACE 8.0f 37 | #define BUTTON_HEIGHT 30.0f 38 | 39 | #define BUTTON_FONT_SIZE 15.0f 40 | #define TEXT_BUTTON_PADDING 24.0f 41 | 42 | #define SHOW_CONTROL_WIDTH 78.0f 43 | #define ICON_BUTTON_WIDTH 40.0f 44 | 45 | #define TITLE_FONT_SIZE 19.0f 46 | #define TITLE_HEIGHT 28.0f 47 | 48 | #pragma mark - Properties 49 | 50 | @synthesize delegate; 51 | 52 | #pragma mark - ThumbsMainToolbar instance methods 53 | 54 | - (instancetype)initWithFrame:(CGRect)frame 55 | { 56 | return [self initWithFrame:frame title:nil]; 57 | } 58 | 59 | - (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title 60 | { 61 | if ((self = [super initWithFrame:frame])) 62 | { 63 | CGFloat viewWidth = self.bounds.size.width; // Toolbar view width 64 | 65 | #if (READER_FLAT_UI == TRUE) // Option 66 | UIImage *buttonH = nil; UIImage *buttonN = nil; 67 | #else 68 | UIImage *buttonH = [[UIImage imageNamed:@"Reader-Button-H"] stretchableImageWithLeftCapWidth:5 topCapHeight:0]; 69 | UIImage *buttonN = [[UIImage imageNamed:@"Reader-Button-N"] stretchableImageWithLeftCapWidth:5 topCapHeight:0]; 70 | #endif // end of READER_FLAT_UI Option 71 | 72 | BOOL largeDevice = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad); 73 | 74 | const CGFloat buttonSpacing = BUTTON_SPACE; //const CGFloat iconButtonWidth = ICON_BUTTON_WIDTH; 75 | 76 | CGFloat titleX = BUTTON_X; CGFloat titleWidth = (viewWidth - (titleX + titleX)); 77 | 78 | CGFloat leftButtonX = BUTTON_X; // Left-side button start X position 79 | 80 | UIFont *doneButtonFont = [UIFont systemFontOfSize:BUTTON_FONT_SIZE]; 81 | NSString *doneButtonText = NSLocalizedString(@"Done", @"button"); 82 | CGSize doneButtonSize = [doneButtonText sizeWithFont:doneButtonFont]; 83 | CGFloat doneButtonWidth = (doneButtonSize.width + TEXT_BUTTON_PADDING); 84 | 85 | UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; 86 | doneButton.frame = CGRectMake(leftButtonX, BUTTON_Y, doneButtonWidth, BUTTON_HEIGHT); 87 | [doneButton setTitleColor:[UIColor colorWithWhite:0.0f alpha:1.0f] forState:UIControlStateNormal]; 88 | [doneButton setTitleColor:[UIColor colorWithWhite:1.0f alpha:1.0f] forState:UIControlStateHighlighted]; 89 | [doneButton setTitle:doneButtonText forState:UIControlStateNormal]; doneButton.titleLabel.font = doneButtonFont; 90 | [doneButton addTarget:self action:@selector(doneButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 91 | [doneButton setBackgroundImage:buttonH forState:UIControlStateHighlighted]; 92 | [doneButton setBackgroundImage:buttonN forState:UIControlStateNormal]; 93 | doneButton.autoresizingMask = UIViewAutoresizingNone; 94 | //doneButton.backgroundColor = [UIColor grayColor]; 95 | doneButton.exclusiveTouch = YES; 96 | 97 | [self addSubview:doneButton]; //leftButtonX += (doneButtonWidth + buttonSpacing); 98 | 99 | titleX += (doneButtonWidth + buttonSpacing); titleWidth -= (doneButtonWidth + buttonSpacing); 100 | 101 | #if (READER_BOOKMARKS == TRUE) // Option 102 | 103 | CGFloat showControlX = (viewWidth - (SHOW_CONTROL_WIDTH + buttonSpacing)); 104 | 105 | UIImage *thumbsImage = [UIImage imageNamed:@"Reader-Thumbs"]; 106 | UIImage *bookmarkImage = [UIImage imageNamed:@"Reader-Mark-Y"]; 107 | NSArray *buttonItems = [NSArray arrayWithObjects:thumbsImage, bookmarkImage, nil]; 108 | 109 | BOOL useTint = [self respondsToSelector:@selector(tintColor)]; // iOS 7 and up 110 | 111 | UISegmentedControl *showControl = [[UISegmentedControl alloc] initWithItems:buttonItems]; 112 | showControl.frame = CGRectMake(showControlX, BUTTON_Y, SHOW_CONTROL_WIDTH, BUTTON_HEIGHT); 113 | showControl.tintColor = (useTint ? [UIColor blackColor] : [UIColor colorWithWhite:0.8f alpha:1.0f]); 114 | showControl.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; 115 | showControl.segmentedControlStyle = UISegmentedControlStyleBar; 116 | showControl.selectedSegmentIndex = 0; // Default segment index 117 | //showControl.backgroundColor = [UIColor grayColor]; 118 | showControl.exclusiveTouch = YES; 119 | 120 | [showControl addTarget:self action:@selector(showControlTapped:) forControlEvents:UIControlEventValueChanged]; 121 | 122 | [self addSubview:showControl]; 123 | 124 | titleWidth -= (SHOW_CONTROL_WIDTH + buttonSpacing); 125 | 126 | #endif // end of READER_BOOKMARKS Option 127 | 128 | if (largeDevice == YES) // Show document filename in toolbar 129 | { 130 | CGRect titleRect = CGRectMake(titleX, BUTTON_Y, titleWidth, TITLE_HEIGHT); 131 | 132 | UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleRect]; 133 | 134 | titleLabel.textAlignment = NSTextAlignmentCenter; 135 | titleLabel.font = [UIFont systemFontOfSize:TITLE_FONT_SIZE]; 136 | titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 137 | titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; 138 | titleLabel.textColor = [UIColor colorWithWhite:0.0f alpha:1.0f]; 139 | titleLabel.backgroundColor = [UIColor clearColor]; 140 | titleLabel.adjustsFontSizeToFitWidth = YES; 141 | titleLabel.minimumScaleFactor = 0.75f; 142 | titleLabel.text = title; 143 | #if (READER_FLAT_UI == FALSE) // Option 144 | titleLabel.shadowColor = [UIColor colorWithWhite:0.65f alpha:1.0f]; 145 | titleLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); 146 | #endif // end of READER_FLAT_UI Option 147 | 148 | [self addSubview:titleLabel]; 149 | } 150 | } 151 | 152 | return self; 153 | } 154 | 155 | #pragma mark - UISegmentedControl action methods 156 | 157 | - (void)showControlTapped:(UISegmentedControl *)control 158 | { 159 | [delegate tappedInToolbar:self showControl:control]; 160 | } 161 | 162 | #pragma mark - UIButton action methods 163 | 164 | - (void)doneButtonTapped:(UIButton *)button 165 | { 166 | [delegate tappedInToolbar:self doneButton:button]; 167 | } 168 | 169 | @end 170 | -------------------------------------------------------------------------------- /Sources/ThumbsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbsViewController.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | #import "ThumbsMainToolbar.h" 29 | #import "ReaderThumbsView.h" 30 | 31 | @class ReaderDocument; 32 | @class ThumbsViewController; 33 | 34 | @protocol ThumbsViewControllerDelegate 35 | 36 | @required // Delegate protocols 37 | 38 | - (void)thumbsViewController:(ThumbsViewController *)viewController gotoPage:(NSInteger)page; 39 | 40 | - (void)dismissThumbsViewController:(ThumbsViewController *)viewController; 41 | 42 | @end 43 | 44 | @interface ThumbsViewController : UIViewController 45 | 46 | @property (nonatomic, weak, readwrite) id delegate; 47 | 48 | - (instancetype)initWithReaderDocument:(ReaderDocument *)object; 49 | 50 | @end 51 | 52 | #pragma mark - 53 | 54 | // 55 | // ThumbsPageThumb class interface 56 | // 57 | 58 | @interface ThumbsPageThumb : ReaderThumbView 59 | 60 | - (CGSize)maximumContentSize; 61 | 62 | - (void)showText:(NSString *)text; 63 | 64 | - (void)showBookmark:(BOOL)show; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /Sources/UIXToolbarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIXToolbarView.h 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface UIXToolbarView : UIView 29 | 30 | @end 31 | 32 | #pragma mark - 33 | 34 | // 35 | // UIXToolbarShadow class interface 36 | // 37 | 38 | @interface UIXToolbarShadow : UIView 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Sources/UIXToolbarView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIXToolbarView.m 3 | // Reader v2.8.6 4 | // 5 | // Created by Julius Oklamcak on 2011-09-01. 6 | // Copyright © 2011-2015 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderConstants.h" 27 | #import "UIXToolbarView.h" 28 | 29 | #import 30 | 31 | @implementation UIXToolbarView 32 | 33 | #pragma mark - Constants 34 | 35 | #define SHADOW_HEIGHT 4.0f 36 | 37 | #pragma mark - UIXToolbarView class methods 38 | 39 | + (Class)layerClass 40 | { 41 | #if (READER_FLAT_UI == FALSE) // Option 42 | return [CAGradientLayer class]; 43 | #else 44 | return [CALayer class]; 45 | #endif // end of READER_FLAT_UI Option 46 | } 47 | 48 | #pragma mark - UIXToolbarView instance methods 49 | 50 | - (instancetype)initWithFrame:(CGRect)frame 51 | { 52 | if ((self = [super initWithFrame:frame])) 53 | { 54 | self.autoresizesSubviews = YES; 55 | self.userInteractionEnabled = YES; 56 | self.contentMode = UIViewContentModeRedraw; 57 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth; 58 | 59 | if ([self.layer isKindOfClass:[CAGradientLayer class]]) 60 | { 61 | self.backgroundColor = [UIColor clearColor]; 62 | 63 | CAGradientLayer *layer = (CAGradientLayer *)self.layer; 64 | UIColor *liteColor = [UIColor colorWithWhite:0.92f alpha:0.8f]; 65 | UIColor *darkColor = [UIColor colorWithWhite:0.32f alpha:0.8f]; 66 | layer.colors = [NSArray arrayWithObjects:(id)liteColor.CGColor, (id)darkColor.CGColor, nil]; 67 | 68 | CGRect shadowRect = self.bounds; shadowRect.origin.y += shadowRect.size.height; shadowRect.size.height = SHADOW_HEIGHT; 69 | 70 | UIXToolbarShadow *shadowView = [[UIXToolbarShadow alloc] initWithFrame:shadowRect]; 71 | 72 | [self addSubview:shadowView]; // Add shadow to toolbar 73 | } 74 | else // Follow The Fuglyosity of Flat Fad 75 | { 76 | self.backgroundColor = [UIColor colorWithWhite:0.94f alpha:0.94f]; 77 | 78 | CGRect lineRect = self.bounds; lineRect.origin.y += lineRect.size.height; lineRect.size.height = 1.0f; 79 | 80 | UIView *lineView = [[UIView alloc] initWithFrame:lineRect]; 81 | lineView.autoresizesSubviews = NO; 82 | lineView.userInteractionEnabled = NO; 83 | lineView.contentMode = UIViewContentModeRedraw; 84 | lineView.autoresizingMask = UIViewAutoresizingFlexibleWidth; 85 | lineView.backgroundColor = [UIColor colorWithWhite:0.64f alpha:0.94f]; 86 | [self addSubview:lineView]; 87 | } 88 | } 89 | 90 | return self; 91 | } 92 | 93 | @end 94 | 95 | #pragma mark - 96 | 97 | // 98 | // UIXToolbarShadow class implementation 99 | // 100 | 101 | @implementation UIXToolbarShadow 102 | 103 | #pragma mark - UIXToolbarShadow class methods 104 | 105 | + (Class)layerClass 106 | { 107 | return [CAGradientLayer class]; 108 | } 109 | 110 | #pragma mark - UIXToolbarShadow instance methods 111 | 112 | - (instancetype)initWithFrame:(CGRect)frame 113 | { 114 | if ((self = [super initWithFrame:frame])) 115 | { 116 | self.autoresizesSubviews = NO; 117 | self.userInteractionEnabled = NO; 118 | self.contentMode = UIViewContentModeRedraw; 119 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth; 120 | self.backgroundColor = [UIColor clearColor]; 121 | 122 | CAGradientLayer *layer = (CAGradientLayer *)self.layer; 123 | UIColor *blackColor = [UIColor colorWithWhite:0.24f alpha:1.0f]; 124 | UIColor *clearColor = [UIColor colorWithWhite:0.24f alpha:0.0f]; 125 | layer.colors = [NSArray arrayWithObjects:(id)blackColor.CGColor, (id)clearColor.CGColor, nil]; 126 | } 127 | 128 | return self; 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /Support/DirectoryWatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // DirectoryWatcher.h 3 | // Version: 1.3 4 | // 5 | // Released by Apple on 2011-03-18. 6 | // Copyright 2011 Apple Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DirectoryWatcher; 12 | 13 | @protocol DirectoryWatcherDelegate 14 | 15 | @required // Delegate protocols 16 | 17 | - (void)directoryDidChange:(DirectoryWatcher *)folderWatcher; 18 | 19 | @end 20 | 21 | @interface DirectoryWatcher : NSObject 22 | { 23 | id __weak delegate; 24 | 25 | CFFileDescriptorRef dirKQRef; 26 | int dirFD; 27 | int kq; 28 | } 29 | 30 | @property (nonatomic, weak, readwrite) id delegate; 31 | 32 | + (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id)watchDelegate; 33 | 34 | - (void)invalidate; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Support/DirectoryWatcher.m: -------------------------------------------------------------------------------- 1 | // 2 | // DirectoryWatcher.m 3 | // Version: 1.3 4 | // 5 | // Released by Apple on 2011-03-18. 6 | // Copyright 2011 Apple Inc. All rights reserved. 7 | // 8 | 9 | #import "DirectoryWatcher.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #import 18 | 19 | @interface DirectoryWatcher (DirectoryWatcherPrivate) 20 | 21 | - (BOOL)startMonitoringDirectory:(NSString *)dirPath; 22 | 23 | - (void)kqueueFired; 24 | 25 | @end 26 | 27 | #pragma mark - 28 | 29 | @implementation DirectoryWatcher 30 | 31 | @synthesize delegate; 32 | 33 | - (id)init 34 | { 35 | self = [super init]; 36 | 37 | delegate = NULL; 38 | dirKQRef = NULL; 39 | dirFD = -1; 40 | kq = -1; 41 | 42 | return self; 43 | } 44 | 45 | - (void)dealloc 46 | { 47 | [self invalidate]; 48 | } 49 | 50 | + (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id)watchDelegate 51 | { 52 | DirectoryWatcher *retVal = NULL; 53 | 54 | if ((watchDelegate != NULL) && (watchPath != NULL)) 55 | { 56 | DirectoryWatcher *tempManager = [[DirectoryWatcher alloc] init]; 57 | 58 | tempManager.delegate = watchDelegate; 59 | 60 | if ([tempManager startMonitoringDirectory:watchPath]) 61 | { 62 | // Everything appears to be in order, so return the DirectoryWatcher. 63 | // Otherwise we'll fall through and return NULL. 64 | retVal = tempManager; 65 | } 66 | } 67 | 68 | return retVal; 69 | } 70 | 71 | - (void)invalidate 72 | { 73 | if (dirKQRef != NULL) 74 | { 75 | CFFileDescriptorInvalidate(dirKQRef); 76 | CFRelease(dirKQRef); dirKQRef = NULL; 77 | // We don't need to close the kq, CFFileDescriptorInvalidate closed it instead. 78 | // Change the value so no one thinks it's still live. 79 | kq = -1; 80 | } 81 | 82 | if (dirFD != -1) 83 | { 84 | close(dirFD); dirFD = -1; 85 | } 86 | } 87 | 88 | @end 89 | 90 | #pragma mark - 91 | 92 | @implementation DirectoryWatcher (DirectoryWatcherPrivate) 93 | 94 | - (void)kqueueFired 95 | { 96 | assert(kq >= 0); 97 | 98 | int eventCount; 99 | struct kevent event; 100 | struct timespec timeout = {0, 0}; 101 | 102 | eventCount = kevent(kq, NULL, 0, &event, 1, &timeout); 103 | 104 | assert((eventCount >= 0) && (eventCount < 2)); 105 | 106 | [delegate directoryDidChange:self]; // call our delegate of the directory change 107 | 108 | CFFileDescriptorEnableCallBacks(dirKQRef, kCFFileDescriptorReadCallBack); 109 | } 110 | 111 | static void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info) 112 | { 113 | DirectoryWatcher *obj; 114 | 115 | obj = (__bridge DirectoryWatcher *)info; 116 | 117 | assert([obj isKindOfClass:[DirectoryWatcher class]]); 118 | assert(callBackTypes == kCFFileDescriptorReadCallBack); 119 | assert(kqRef == obj->dirKQRef); 120 | 121 | [obj kqueueFired]; 122 | } 123 | 124 | - (BOOL)startMonitoringDirectory:(NSString *)dirPath 125 | { 126 | // Double initializing is not going to work... 127 | if ((dirKQRef == NULL) && (dirFD == -1) && (kq == -1)) 128 | { 129 | // Open the directory we're going to watch 130 | dirFD = open([dirPath fileSystemRepresentation], O_EVTONLY); 131 | 132 | if (dirFD >= 0) 133 | { 134 | // Create a kqueue for our event messages... 135 | kq = kqueue(); 136 | 137 | if (kq >= 0) 138 | { 139 | struct kevent eventToAdd; 140 | 141 | eventToAdd.ident = dirFD; 142 | eventToAdd.filter = EVFILT_VNODE; 143 | eventToAdd.flags = EV_ADD | EV_CLEAR; 144 | eventToAdd.fflags = NOTE_WRITE; 145 | eventToAdd.udata = NULL; 146 | eventToAdd.data = 0; 147 | 148 | int errNum = kevent(kq, &eventToAdd, 1, NULL, 0, NULL); 149 | 150 | if (errNum == 0) 151 | { 152 | CFRunLoopSourceRef rls; 153 | CFFileDescriptorContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; 154 | 155 | // Passing true in the third argument so CFFileDescriptorInvalidate will close kq. 156 | dirKQRef = CFFileDescriptorCreate(NULL, kq, true, KQCallback, &context); 157 | 158 | if (dirKQRef != NULL) 159 | { 160 | rls = CFFileDescriptorCreateRunLoopSource(NULL, dirKQRef, 0); 161 | 162 | if (rls != NULL) 163 | { 164 | CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); 165 | 166 | CFFileDescriptorEnableCallBacks(dirKQRef, kCFFileDescriptorReadCallBack); 167 | 168 | // If everything worked, return early and bypass shutting things down 169 | return YES; 170 | } 171 | 172 | // Couldn't create a runloop source, invalidate and release the CFFileDescriptorRef 173 | CFFileDescriptorInvalidate(dirKQRef); 174 | CFRelease(dirKQRef); dirKQRef = NULL; 175 | } 176 | } 177 | 178 | // kq is active, but something failed, close the handle... 179 | close(kq); kq = -1; 180 | } 181 | 182 | // file handle is open, but something failed, close the handle... 183 | close(dirFD); dirFD = -1; 184 | } 185 | } 186 | 187 | return NO; 188 | } 189 | 190 | @end 191 | -------------------------------------------------------------------------------- /Support/DocumentsUpdate.h: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentsUpdate.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | @interface DocumentsUpdate : NSObject 29 | 30 | + (DocumentsUpdate *)sharedInstance; 31 | 32 | + (NSString *)documentsPath; 33 | 34 | - (void)cancelAllOperations; 35 | 36 | - (void)queueDocumentsUpdate; 37 | 38 | - (BOOL)handleOpenURL:(NSURL *)theURL; 39 | 40 | extern NSString *const DocumentsUpdateOpenNotification; 41 | 42 | @end 43 | 44 | #pragma mark - 45 | 46 | // 47 | // DocumentsUpdateOperation class interface 48 | // 49 | 50 | @interface DocumentsUpdateOperation : NSOperation 51 | 52 | extern NSString *const DocumentsUpdateNotification; 53 | extern NSString *const DocumentsUpdateAddedObjectIDs; 54 | extern NSString *const DocumentsUpdateDeletedObjectIDs; 55 | extern NSString *const DocumentsUpdateBeganNotification; 56 | extern NSString *const DocumentsUpdateEndedNotification; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Support/DocumentsUpdate.m: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentsUpdate.m 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderConstants.h" 27 | #import "DocumentsUpdate.h" 28 | #import "CoreDataManager.h" 29 | #import "ReaderDocument.h" 30 | 31 | @implementation DocumentsUpdate 32 | { 33 | NSOperationQueue *workQueue; 34 | } 35 | 36 | #pragma mark DocumentsUpdate class methods 37 | 38 | + (DocumentsUpdate *)sharedInstance 39 | { 40 | static dispatch_once_t predicate = 0; 41 | 42 | static DocumentsUpdate *object = nil; // Object 43 | 44 | dispatch_once(&predicate, ^{ object = [self new]; }); 45 | 46 | return object; // DocumentsUpdate singleton 47 | } 48 | 49 | + (NSString *)documentsPath 50 | { 51 | NSArray *documentsPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 52 | 53 | return [documentsPaths objectAtIndex:0]; // Path to the application's "~/Documents" directory 54 | } 55 | 56 | #pragma mark DocumentsUpdate instance methods 57 | 58 | - (id)init 59 | { 60 | if ((self = [super init])) 61 | { 62 | workQueue = [NSOperationQueue new]; 63 | 64 | [workQueue setName:@"DocumentsUpdateWorkQueue"]; 65 | 66 | [workQueue setMaxConcurrentOperationCount:1]; 67 | } 68 | 69 | return self; 70 | } 71 | 72 | - (void)cancelAllOperations 73 | { 74 | [workQueue cancelAllOperations]; 75 | } 76 | 77 | - (void)queueDocumentsUpdate 78 | { 79 | if (workQueue.operationCount < 1) // Limit the number of DocumentsUpdate operations in work queue 80 | { 81 | DocumentsUpdateOperation *updateOp = [DocumentsUpdateOperation new]; [updateOp setThreadPriority:0.25]; 82 | 83 | [workQueue addOperation:updateOp]; // Queue up a documents update operation 84 | } 85 | } 86 | 87 | - (BOOL)handleOpenURL:(NSURL *)theURL 88 | { 89 | BOOL handled = NO; // Handled flag 90 | 91 | if ([theURL isFileURL] == YES) // File URLs only 92 | { 93 | NSString *inboxFilePath = [theURL path]; // File path string 94 | 95 | NSString *inboxPath = [inboxFilePath stringByDeletingLastPathComponent]; 96 | 97 | if ([[inboxPath lastPathComponent] isEqualToString:@"Inbox"]) // Inbox test 98 | { 99 | NSString *documentFile = [inboxFilePath lastPathComponent]; // File name 100 | 101 | NSString *documentsPath = [DocumentsUpdate documentsPath]; // Documents path 102 | 103 | NSString *documentFilePath = [documentsPath stringByAppendingPathComponent:documentFile]; 104 | 105 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 106 | 107 | [fileManager moveItemAtPath:inboxFilePath toPath:documentFilePath error:NULL]; // Move 108 | 109 | [fileManager removeItemAtPath:inboxPath error:NULL]; // Delete Inbox directory 110 | 111 | NSManagedObjectContext *mainMOC = [[CoreDataManager sharedInstance] mainManagedObjectContext]; 112 | 113 | NSArray *documentList = [ReaderDocument allInMOC:mainMOC withName:documentFile]; 114 | 115 | ReaderDocument *document = nil; // ReaderDocument object 116 | 117 | if (documentList.count > 0) // Document exists 118 | { 119 | document = [documentList objectAtIndex:0]; 120 | } 121 | else // Insert the new document into the object store 122 | { 123 | document = [ReaderDocument insertInMOC:mainMOC name:documentFile path:documentsPath]; 124 | 125 | [[CoreDataManager sharedInstance] saveMainManagedObjectContext]; // Save changes 126 | } 127 | 128 | if (document != nil) // We have a document to show 129 | { 130 | NSString *documentURI = [[[document objectID] URIRepresentation] absoluteString]; // Document URI 131 | 132 | [[NSUserDefaults standardUserDefaults] setObject:documentURI forKey:kReaderSettingsCurrentDocument]; 133 | 134 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 135 | 136 | [notificationCenter postNotificationName:DocumentsUpdateOpenNotification object:nil userInfo:nil]; 137 | 138 | handled = YES; // We handled the open URL request 139 | } 140 | } 141 | } 142 | 143 | return handled; 144 | } 145 | 146 | #pragma mark Notification name strings 147 | 148 | NSString *const DocumentsUpdateOpenNotification = @"DocumentsUpdateOpenNotification"; 149 | 150 | @end 151 | 152 | #pragma mark - 153 | 154 | // 155 | // DocumentsUpdateOperation class implementation 156 | // 157 | 158 | @implementation DocumentsUpdateOperation 159 | 160 | #pragma mark DocumentsUpdateOperation methods 161 | 162 | - (void)main 163 | { 164 | __autoreleasing NSError *error = nil; // Error information object 165 | 166 | NSString *documentsPath = [DocumentsUpdate documentsPath]; // Documents path 167 | 168 | NSFileManager *fileManager = [NSFileManager new]; // File manager instance 169 | 170 | NSArray *fileList = [fileManager contentsOfDirectoryAtPath:documentsPath error:&error]; 171 | 172 | if (fileList != nil) // Process documents directory contents 173 | { 174 | NSMutableSet *fileSet = [NSMutableSet new]; // File name set 175 | 176 | for (NSString *fileName in fileList) // Enumerate directory contents 177 | { 178 | if ([[fileName pathExtension] caseInsensitiveCompare:@"pdf"] == NSOrderedSame) 179 | { 180 | [fileSet addObject:fileName]; // Add the '.pdf' file to the file set 181 | } 182 | } 183 | 184 | NSMutableSet *dataSet = [NSMutableSet new]; // Database file name set 185 | 186 | NSMutableDictionary *nameDictionary = [NSMutableDictionary new]; // Objects 187 | 188 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 189 | 190 | NSManagedObjectContext *workMOC = [[CoreDataManager sharedInstance] newManagedObjectContext]; 191 | 192 | [notificationCenter addObserver:self selector:@selector(handleContextDidSaveNotification:) 193 | name:NSManagedObjectContextDidSaveNotification object:workMOC]; 194 | 195 | NSArray *documentList = [ReaderDocument allInMOC:workMOC]; // All document objects 196 | 197 | for (ReaderDocument *document in documentList) // Enumerate document objects 198 | { 199 | NSString *fileName = document.fileName; // Get the document file name 200 | 201 | [nameDictionary setObject:document forKey:fileName]; // Track objects 202 | 203 | [dataSet addObject:fileName]; // Add the file name to the data set 204 | } 205 | 206 | NSMutableSet *addSet = [fileSet mutableCopy]; [addSet minusSet:dataSet]; // Add set 207 | 208 | NSMutableSet *delSet = [dataSet mutableCopy]; [delSet minusSet:fileSet]; // Delete set 209 | 210 | BOOL postUpdate = (((addSet.count > 0) || (delSet.count > 0)) ? YES : NO); 211 | 212 | if (postUpdate) [notificationCenter postNotificationName:DocumentsUpdateBeganNotification object:nil userInfo:nil]; 213 | 214 | for (NSString *fileName in addSet) // Enumerate documents to add set 215 | { 216 | NSString *fullFilePath = [documentsPath stringByAppendingPathComponent:fileName]; 217 | 218 | NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:fullFilePath error:NULL]; 219 | 220 | NSDate *fileDate = [fileAttributes objectForKey:NSFileModificationDate]; // File date 221 | 222 | NSTimeInterval timeInterval = fabs([fileDate timeIntervalSinceNow]); // File age 223 | 224 | if (timeInterval > 10.0) // Add the file - iOS 5 file sharing sync hack'n'kludge'n'bodge 225 | { 226 | ReaderDocument *object = [ReaderDocument insertInMOC:workMOC name:fileName path:documentsPath]; 227 | 228 | assert(object != nil); // Object insert failure should never happen 229 | } 230 | } 231 | 232 | for (NSString *fileName in delSet) // Enumerate documents to delete set 233 | { 234 | ReaderDocument *object = [nameDictionary objectForKey:fileName]; // Object 235 | 236 | [ReaderDocument deleteInMOC:workMOC object:object fm:fileManager]; // Delete 237 | } 238 | 239 | if ([workMOC hasChanges] == YES) // Save changes 240 | { 241 | if ([workMOC save:&error] == NO) // Log any errors 242 | { 243 | NSLog(@"%s %@", __FUNCTION__, error); assert(NO); 244 | } 245 | } 246 | 247 | [notificationCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:workMOC]; 248 | 249 | if (postUpdate) [notificationCenter postNotificationName:DocumentsUpdateEndedNotification object:nil userInfo:nil]; 250 | } 251 | else // Log any errors 252 | { 253 | NSLog(@"%s %@", __FUNCTION__, error); assert(NO); 254 | } 255 | } 256 | 257 | #pragma mark Notification observer methods 258 | 259 | - (void)handleContextDidSaveNotification:(NSNotification *)notification 260 | { 261 | dispatch_sync(dispatch_get_main_queue(), // Merge synchronously on main thread 262 | ^{ 263 | NSManagedObjectContext *mainMOC = [[CoreDataManager sharedInstance] mainManagedObjectContext]; 264 | 265 | [mainMOC mergeChangesFromContextDidSaveNotification:notification]; // Merge the changes 266 | }); 267 | 268 | NSDictionary *userInfo = [notification userInfo]; // Notification information 269 | 270 | if (userInfo != nil) // Process the user notification information 271 | { 272 | NSMutableSet *deletedObjectIDs = [NSMutableSet new]; // Deleted set 273 | 274 | NSArray *deletedObjects = [userInfo objectForKey:NSDeletedObjectsKey]; 275 | 276 | if (deletedObjects != nil) // We have deleted objects 277 | { 278 | for (NSManagedObject *object in deletedObjects) // Enumerate them 279 | { 280 | [deletedObjectIDs addObject:[object objectID]]; // Add object ID 281 | } 282 | } 283 | 284 | NSMutableSet *insertedObjectIDs = [NSMutableSet new]; // Inserted set 285 | 286 | NSArray *insertedObjects = [userInfo objectForKey:NSInsertedObjectsKey]; 287 | 288 | if (insertedObjects != nil) // We have inserted objects 289 | { 290 | for (NSManagedObject *object in insertedObjects) // Enumerate them 291 | { 292 | [insertedObjectIDs addObject:[object objectID]]; // Add object ID 293 | } 294 | } 295 | 296 | NSMutableDictionary *updateInfo = [NSMutableDictionary new]; // Update info 297 | 298 | if (deletedObjectIDs.count > 0) // We have deleted object IDs 299 | { 300 | [updateInfo setObject:deletedObjectIDs forKey:DocumentsUpdateDeletedObjectIDs]; 301 | } 302 | 303 | if (insertedObjectIDs.count > 0) // We have inserted object IDs 304 | { 305 | [updateInfo setObject:insertedObjectIDs forKey:DocumentsUpdateAddedObjectIDs]; 306 | } 307 | 308 | if (updateInfo.count > 0) // Post an update notification 309 | { 310 | dispatch_async(dispatch_get_main_queue(), // Notify asynchronously on main thread 311 | ^{ 312 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 313 | 314 | [notificationCenter postNotificationName:DocumentsUpdateNotification object:nil userInfo:updateInfo]; 315 | }); 316 | } 317 | } 318 | } 319 | 320 | #pragma mark Notification name strings 321 | 322 | NSString *const DocumentsUpdateNotification = @"DocumentsUpdateNotification"; 323 | NSString *const DocumentsUpdateAddedObjectIDs = @"DocumentsUpdateAddedObjectIDs"; 324 | NSString *const DocumentsUpdateDeletedObjectIDs = @"DocumentsUpdateDeletedObjectIDs"; 325 | NSString *const DocumentsUpdateBeganNotification = @"DocumentsUpdateBeganNotification"; 326 | NSString *const DocumentsUpdateEndedNotification = @"DocumentsUpdateEndedNotification"; 327 | 328 | @end 329 | -------------------------------------------------------------------------------- /Support/ReaderConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderConstants.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #if !__has_feature(objc_arc) 27 | #error ARC (-fobjc-arc) is required to build this code. 28 | #endif 29 | 30 | #import 31 | 32 | #define READER_FLAT_UI TRUE 33 | #define READER_SHOW_SHADOWS TRUE 34 | #define READER_ENABLE_THUMBS TRUE 35 | #define READER_DISABLE_RETINA FALSE 36 | #define READER_ENABLE_PREVIEW TRUE 37 | #define READER_DISABLE_IDLE FALSE 38 | #define READER_STANDALONE FALSE 39 | #define READER_BOOKMARKS TRUE 40 | 41 | extern NSString *const kReaderCopyrightNotice; 42 | 43 | extern NSString *const kReaderSettingsAppVersion; 44 | extern NSString *const kReaderSettingsCurrentFolder; 45 | extern NSString *const kReaderSettingsCurrentDocument; 46 | extern NSString *const kReaderSettingsHideStatusBar; 47 | -------------------------------------------------------------------------------- /Support/ReaderConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReaderConstants.m 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import "ReaderConstants.h" 27 | 28 | NSString *const kReaderCopyrightNotice = @"Viewer v1.x.y • Copyright © 2011-2014 Julius Oklamcak. All rights reserved."; 29 | 30 | NSString *const kReaderSettingsAppVersion = @"AppVersion"; 31 | NSString *const kReaderSettingsCurrentFolder = @"CurrentFolder"; 32 | NSString *const kReaderSettingsCurrentDocument = @"CurrentDocument"; 33 | NSString *const kReaderSettingsHideStatusBar = @"HideStatusBar"; 34 | -------------------------------------------------------------------------------- /Support/UIXTextEntry.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIXTextEntry.h 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | typedef enum 29 | { 30 | UIXTextEntryTypeURL, 31 | UIXTextEntryTypeText, 32 | UIXTextEntryTypeSecure 33 | } UIXTextEntryType; 34 | 35 | @class UIXTextEntry; 36 | 37 | @protocol UIXTextEntryDelegate 38 | 39 | @required // Delegate protocols 40 | 41 | - (BOOL)textEntryShouldReturn:(UIXTextEntry *)textEntry text:(NSString *)text; 42 | 43 | - (void)doneButtonTappedInTextEntry:(UIXTextEntry *)textEntry text:(NSString *)text; 44 | 45 | - (void)cancelButtonTappedInTextEntry:(UIXTextEntry *)textEntry; 46 | 47 | @end 48 | 49 | @interface UIXTextEntry : UIView 50 | 51 | @property (nonatomic, weak, readwrite) id delegate; 52 | 53 | - (void)setStatus:(NSString *)text; 54 | 55 | - (void)setTextField:(NSString *)text; 56 | 57 | - (void)setTitle:(NSString *)text withType:(UIXTextEntryType)type; 58 | 59 | - (void)animateHide; 60 | - (void)animateShow; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Todo.txt: -------------------------------------------------------------------------------- 1 | 2 | - TBD 3 | -------------------------------------------------------------------------------- /Viewer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleInfoDictionaryVersion 6 | 6.0 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleIconFiles 10 | 11 | AppIcon-180.png 12 | AppIcon-167.png 13 | AppIcon-152.png 14 | AppIcon-144.png 15 | AppIcon-120.png 16 | AppIcon-114.png 17 | AppIcon-076.png 18 | AppIcon-072.png 19 | AppIcon-057.png 20 | 21 | CFBundleName 22 | ${PRODUCT_NAME} 23 | CFBundleDisplayName 24 | ${PRODUCT_NAME} 25 | CFBundleExecutable 26 | ${EXECUTABLE_NAME} 27 | CFBundleIdentifier 28 | com.example.${PRODUCT_NAME:rfc1034identifier} 29 | CFBundlePackageType 30 | APPL 31 | CFBundleSignature 32 | ???? 33 | CFBundleVersion 34 | 1.2.2 35 | CFBundleShortVersionString 36 | 1.2.2 37 | LSRequiresIPhoneOS 38 | 39 | UIPrerenderedIcon 40 | 41 | UIRequiresFullScreen 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeRight 48 | UIInterfaceOrientationLandscapeLeft 49 | 50 | UIFileSharingEnabled 51 | 52 | CFBundleDocumentTypes 53 | 54 | 55 | CFBundleTypeName 56 | PDF Document 57 | CFBundleTypeExtensions 58 | 59 | pdf 60 | 61 | LSItemContentTypes 62 | 63 | com.adobe.pdf 64 | 65 | CFBundleTypeIconFiles 66 | 67 | AppIcon-PDF.png 68 | 69 | 70 | 71 | UILaunchStoryboardName 72 | Viewer-App 73 | UILaunchImages 74 | 75 | 76 | UILaunchImageName 77 | Default 78 | UILaunchImageMinimumOSVersion 79 | 7.0 80 | UILaunchImageOrientation 81 | Portrait 82 | UILaunchImageSize 83 | {320, 568} 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /Viewer-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Viewer-Prefix.pch 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #ifdef __OBJC__ 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | #endif 34 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Viewer v1.2.0 4 | // 5 | // Created by Julius Oklamcak on 2012-09-01. 6 | // Copyright © 2011-2014 Julius Oklamcak. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | // of the Software, and to permit persons to whom the Software is furnished to 13 | // do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | #import 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | @autoreleasepool 31 | { 32 | return UIApplicationMain(argc, argv, nil, @"ViewerAppDelegate"); 33 | } 34 | } 35 | --------------------------------------------------------------------------------