// // CPDFViewController.m // viewer-ctrl-demo // // Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved. // // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. // This notice may not be removed from this file. // #import "CPDFViewController.h" #import #import @interface CPDFViewController () @property(nonatomic, strong) NSString *filePath; @property(nonatomic, strong) CPDFListView *pdfListView; @property(nonatomic, strong) CNavigationRightView *rightView; @property(nonatomic, strong) CSearchToolbar *searchToolbar; @property(nonatomic, strong) CActivityIndicatorView *loadingView; @property(nonatomic, strong) NSString *navigationTitle; @property(nonatomic, strong) CNavigationBarTitleButton * titleButton; @property(nonatomic, strong) CPDFPopMenu *popMenu; @property(nonatomic, assign) BOOL popMenuClosed; @end @implementation CPDFViewController #pragma mark - Initializers - (instancetype)initWithFilePath:(NSString *)filePath { if(self = [super init]) { self.filePath = filePath; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [CPDFColorUtils CPDFViewControllerBackgroundColor]; self.pdfListView = [[CPDFListView alloc] initWithFrame:self.view.bounds]; self.pdfListView.performDelegate = self; self.pdfListView.delegate = self; self.pdfListView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:self.pdfListView]; CPDFEditingConfig *editingConfig = [[CPDFEditingConfig alloc]init]; editingConfig.editingBorderWidth = 1.0; editingConfig.editingOffsetGap = 5; self.pdfListView.editingConfig = editingConfig; UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"CPDFThunbnailImageEnter" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil] style:UIBarButtonItemStylePlain target:self action:@selector(buttonItemClicked_thumbnail:)]; self.navigationItem.leftBarButtonItem = leftItem; __block typeof(self) blockSelf = self; self.rightView = [[CNavigationRightView alloc] initWithDefaultItemsClickBack:^(NSUInteger tag) { switch (tag) { case CNavigationRightTypeSearch: [blockSelf navigationRightItemSearch]; break; case CNavigationRightTypeBota: [blockSelf navigationRightItemBota]; break; default: case CNavigationRightTypeMore: [blockSelf navigationRightItemMore]; break; } }]; self.searchToolbar = [[CSearchToolbar alloc] initWithPDFView:self.pdfListView]; self.searchToolbar.delegate = self; [self reloadDocumentWithFilePath:self.filePath completion:^(BOOL result) { }]; } - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; if(!self.popMenuClosed) { if (@available(iOS 11.0, *)) { [self.popMenu showMenuInRect:CGRectMake(self.view.frame.size.width - self.view.safeAreaInsets.right - 250, CGRectGetMaxY(self.navigationController.navigationBar.frame), 250, 200)]; } else { // Fallback on earlier versions [self.popMenu showMenuInRect:CGRectMake(self.view.frame.size.width - 250, CGRectGetMaxY(self.navigationController.navigationBar.frame), 250, 200)]; } } CGFloat tPosY = 0; CGFloat bottomY = 0; CGFloat height = 0; if (@available(iOS 11.0, *)) height += self.view.safeAreaInsets.bottom; if (!self.navigationController.navigationBarHidden) { CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame]; tPosY = self.navigationController.navigationBar.frame.size.height + rectStatus.size.height; } else { bottomY = 0; } if (@available(iOS 11.0, *)) { self.pdfListView.frame = CGRectMake(self.view.safeAreaInsets.left, tPosY, self.view.frame.size.width - self.view.safeAreaInsets.left - self.view.safeAreaInsets.right, self.view.frame.size.height - tPosY- bottomY); } else { self.pdfListView.frame = CGRectMake(0, tPosY, self.view.frame.size.width, self.view.frame.size.height - tPosY-bottomY); } } #pragma mark - Accessors #pragma mark - Public method - (void)reloadDocumentWithFilePath:(NSString *)filePath completion:(void (^)(BOOL result))completion { self.title = [[filePath lastPathComponent] stringByDeletingPathExtension]; _navigationTitle = self.title; // [self.titleButton setTitle:self.title forState:UIControlStateNormal]; [self.navigationController.view setUserInteractionEnabled:NO]; if (![self.loadingView superview]) { [self.view addSubview:self.loadingView]; } [self.loadingView startAnimating]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSURL *url = [NSURL fileURLWithPath:filePath]; CPDFDocument *document = [[CPDFDocument alloc] initWithURL:url]; dispatch_async(dispatch_get_main_queue(), ^{ [self.navigationController.view setUserInteractionEnabled:YES]; [self.loadingView stopAnimating]; [self.loadingView removeFromSuperview]; if (document.error && document.error.code != CPDFDocumentPasswordError) { UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self.navigationController popViewControllerAnimated:YES]; }]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:NSLocalizedString(@"Sorry PDF Reader Can't open this pdf file!", nil) preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:okAction]; if (completion) { completion(NO); } } else { self.pdfListView.document = document; if (completion) { completion(YES); } } }); }); } #pragma mark - Action - (void)navigationRightItemSearch { [self.searchToolbar showInView:self.navigationController.navigationBar]; self.title = nil; self.navigationItem.rightBarButtonItem = nil; self.navigationItem.leftBarButtonItem = nil; } - (void)navigationRightItemBota { CPDFBOTAViewController *botaViewController = [[CPDFBOTAViewController alloc] initWithPDFView:self.pdfListView]; botaViewController.delegate = self; AAPLCustomPresentationController *presentationController NS_VALID_UNTIL_END_OF_SCOPE; presentationController = [[AAPLCustomPresentationController alloc] initWithPresentedViewController:botaViewController presentingViewController:self]; botaViewController.transitioningDelegate = presentationController; [self presentViewController:botaViewController animated:YES completion:nil]; } - (void)navigationRightItemMore { CPDFPopMenuView * menuView = [[CPDFPopMenuView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; menuView.delegate = self; self.popMenu = [CPDFPopMenu popMenuWithContentView:menuView]; self.popMenu.dimCoverLayer = YES; self.popMenu.delegate = self; if (@available(iOS 11.0, *)) { [self.popMenu showMenuInRect:CGRectMake(self.view.frame.size.width - self.view.safeAreaInsets.right - 250, CGRectGetMaxY(self.navigationController.navigationBar.frame), 250, 200)]; } else { // Fallback on earlier versions [self.popMenu showMenuInRect:CGRectMake(self.view.frame.size.width - 250, CGRectGetMaxY(self.navigationController.navigationBar.frame), 250, 200)]; } } - (void)buttonItemClicked_thumbnail:(id)sender { CPDFThumbnailViewController *thumbnailViewController = [[CPDFThumbnailViewController alloc] initWithPDFView:self.pdfListView]; thumbnailViewController.delegate = self; AAPLCustomPresentationController *presentationController NS_VALID_UNTIL_END_OF_SCOPE; presentationController = [[AAPLCustomPresentationController alloc] initWithPresentedViewController:thumbnailViewController presentingViewController:self]; thumbnailViewController.transitioningDelegate = presentationController; [self presentViewController:thumbnailViewController animated:YES completion:nil]; } - (void)menuItemClick_CopyAction:(id)sender { if (self.pdfListView.currentSelection.string) [[UIPasteboard generalPasteboard] setString:self.pdfListView.currentSelection.string]; [self.pdfListView clearSelection]; } #pragma mark - CPDFViewDelegate - (void)PDFViewDocumentDidLoaded:(CPDFView *)pdfView { UIBarButtonItem* rightItem = [[UIBarButtonItem alloc] initWithCustomView:self.rightView]; self.navigationItem.rightBarButtonItem = rightItem; } - (void)PDFViewCurrentPageDidChanged:(CPDFView *)pdfView { NSLog(@""); } #pragma mark - CPDFListViewDelegate - (void)PDFListViewPerformTouchEnded:(CPDFListView *)pdfView { CGFloat tPosY = 0; if (self.navigationController.navigationBarHidden) { [self.navigationController setNavigationBarHidden:NO animated:YES]; [UIView animateWithDuration:0.3 animations:^{ self.pdfListView.pageSliderView.alpha = 1.0; }]; CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame]; tPosY = self.navigationController.navigationBar.frame.size.height + rectStatus.size.height; } else { [self.navigationController setNavigationBarHidden:YES animated:YES]; [UIView animateWithDuration:0.3 animations:^{ self.pdfListView.pageSliderView.alpha = 0.0; }]; } if (@available(iOS 11.0, *)) { self.pdfListView.frame = CGRectMake(self.view.safeAreaInsets.left, tPosY, self.view.frame.size.width - self.view.safeAreaInsets.left - self.view.safeAreaInsets.right, self.view.frame.size.height - self.view.safeAreaInsets.bottom- tPosY); } else { self.pdfListView.frame = CGRectMake(0, tPosY, self.view.frame.size.width, self.view.frame.size.height - tPosY); } } #pragma mark - CSearchToolbarDelegate - (void)searchToolbar:(CSearchToolbar *)searchToolbar onSearchQueryResults:(NSArray *)results { if ([results count] < 1) { UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleCancel handler:nil]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:NSLocalizedString(@"your have‘t search result", nil) preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:cancelAction]; [self presentViewController:alert animated:YES completion:nil]; return; } CPDFSearchResultsViewController* searchResultController = [[CPDFSearchResultsViewController alloc] initWithResultArray:results keyword:searchToolbar.searchKeyString document:self.pdfListView.document]; searchResultController.delegate = self; AAPLCustomPresentationController *presentationController NS_VALID_UNTIL_END_OF_SCOPE; presentationController = [[AAPLCustomPresentationController alloc] initWithPresentedViewController:searchResultController presentingViewController:self]; searchResultController.transitioningDelegate = presentationController; [self presentViewController:searchResultController animated:YES completion:nil]; } - (void)searchToolbarOnExitSearch:(CSearchToolbar *)searchToolbar { if([searchToolbar superview]) { [searchToolbar removeFromSuperview]; UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithCustomView:self.rightView]; self.navigationItem.rightBarButtonItem = rightItem; self.title = self.navigationTitle; UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"CPDFThunbnailImageEnter" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil] style:UIBarButtonItemStylePlain target:self action:@selector(buttonItemClicked_thumbnail:)]; self.navigationItem.leftBarButtonItem = leftItem; } } #pragma mark - CPDFDisplayViewDelegate - (void)displayViewControllerDismiss:(CPDFDisplayViewController *)displayViewController { [self.navigationController popToRootViewControllerAnimated:YES]; } #pragma mark - CPDFBOTAViewControllerDelegate - (void)botaViewControllerDismiss:(CPDFBOTAViewController *)botaViewController { [self.navigationController dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - CPDFSearchResultsDelegate - (void)searchResultsView:(CPDFSearchResultsViewController *)resultVC forSelection:(CPDFSelection *)selection indexPath:(NSIndexPath *)indexPath { [self.navigationController popViewControllerAnimated:YES]; NSInteger pageIndex = [self.pdfListView.document indexForPage:selection.page]; [self.pdfListView goToPageIndex:pageIndex animated:NO]; [self.pdfListView setHighlightedSelection:selection animated:YES]; } -(void)searchResultsViewControllerDismiss:(CPDFSearchResultsViewController *)searchResultsViewController { [self.navigationController popViewControllerAnimated:YES]; } #pragma mark - CPDFPopMenuDelegate - (void)menuDidClosedIn:(CPDFPopMenu *)menu isClosed:(BOOL)isClosed { self.popMenuClosed = isClosed; } #pragma mark - CPDFThumbnailViewControllerDelegate - (void)thumbnailViewController:(CPDFThumbnailViewController *)thumbnailViewController pageIndex:(NSInteger)pageIndex { [self.pdfListView goToPageIndex:pageIndex animated:NO]; [self.navigationController popViewControllerAnimated:YES]; } #pragma mark - CPDFMenuViewdelegate - (void)menuDidClickAtView:(CPDFPopMenuView *)view clickType:(CPDFPopMenuViewType)viewType { switch (viewType) { case CPDFPopMenuViewTypeSetting: //display controller { [self.popMenu hideMenu]; CPDFDisplayViewController *displayVc = [[CPDFDisplayViewController alloc] initWithPDFView:self.pdfListView]; displayVc.delegate = self; AAPLCustomPresentationController *presentationController NS_VALID_UNTIL_END_OF_SCOPE; presentationController = [[AAPLCustomPresentationController alloc] initWithPresentedViewController:displayVc presentingViewController:self]; displayVc.transitioningDelegate = presentationController; [self presentViewController:displayVc animated:YES completion:nil]; } break; case CPDFPopMenuViewTypeInfo: { [self.popMenu hideMenu]; CPDFInfoViewController * infoVc = [[CPDFInfoViewController alloc] initWithPDFView:self.pdfListView]; AAPLCustomPresentationController *presentationController NS_VALID_UNTIL_END_OF_SCOPE; presentationController = [[AAPLCustomPresentationController alloc] initWithPresentedViewController:infoVc presentingViewController:self]; infoVc.transitioningDelegate = presentationController; [self presentViewController:infoVc animated:YES completion:nil]; } break; case CPDFPopMenuViewTypeShare: { [self.popMenu hideMenu]; if (self.pdfListView.isEdited) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self.pdfListView commitEditing]; dispatch_async(dispatch_get_main_queue(), ^{ [self.pdfListView endOfEditing]; [self shareAction]; }); }); } else { [self.pdfListView endOfEditing]; [self shareAction]; } } break; case CPDFPopMenuViewTypeAddFile: { [self.popMenu hideMenu]; NSArray *documentTypes = @[@"com.adobe.pdf"]; UIDocumentPickerViewController *documentPickerViewController = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:documentTypes inMode:UIDocumentPickerModeOpen]; documentPickerViewController.delegate = self; [self presentViewController:documentPickerViewController animated:YES completion:nil]; } default: break; } } - (void)shareAction { UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:@[self.pdfListView.document.documentURL] applicationActivities:nil]; activityVC.definesPresentationContext = YES; [self presentViewController:activityVC animated:YES completion:nil]; activityVC.completionWithItemsHandler = ^(UIActivityType _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) { if (completed) { NSLog(@"Success!"); } else { NSLog(@"Failed Or Canceled!"); } }; } #pragma mark - UIDocument Picker - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray *)urls{ __weak typeof(self) weakSelf = self; BOOL fileUrlAuthozied = [urls.firstObject startAccessingSecurityScopedResource]; if(fileUrlAuthozied){ NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init]; NSError *error; [fileCoordinator coordinateReadingItemAtURL:urls.firstObject options:0 error:&error byAccessor:^(NSURL *newURL) { NSFileManager * fileManager = [NSFileManager defaultManager]; NSString * appDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString *fileName = [newURL lastPathComponent]; NSString * filePath = [appDir stringByAppendingPathComponent:fileName]; if(![fileManager fileExistsAtPath:filePath]) { BOOL filePresent = [weakSelf copyMissingFile:newURL.path toPath:appDir]; NSString * savedPath = [NSString stringWithFormat:@"%@/%@",appDir,fileName]; [weakSelf reloadDocumentWithFilePath:savedPath completion:^(BOOL result) { [weakSelf.pdfListView reloadInputViews]; }]; } NSError *error = nil; if (error) { // } else { } [self dismissViewControllerAnimated:YES completion:NULL]; }]; [urls.firstObject stopAccessingSecurityScopedResource]; }else{ //Error handling NSLog(@"Faild"); } } - (BOOL)copyMissingFile:(NSString*)sourcePath toPath:(NSString*)toPath { BOOL retVal = YES; NSString * finalLocation = [toPath stringByAppendingPathComponent:[sourcePath lastPathComponent]]; if(![[NSFileManager defaultManager] fileExistsAtPath:finalLocation]) { retVal = [[NSFileManager defaultManager] copyItemAtPath:sourcePath toPath:finalLocation error:NULL]; } return retVal; } @end