diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitView.m b/ios/RCTPSPDFKit/RCTPSPDFKitView.m index acc24afc..e10ff7f2 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitView.m +++ b/ios/RCTPSPDFKit/RCTPSPDFKitView.m @@ -15,6 +15,19 @@ #define VALIDATE_DOCUMENT(document, ...) { if (!document.isValid) { NSLog(@"Document is invalid."); if (self.onDocumentLoadFailed) { self.onDocumentLoadFailed(@{@"error": @"Document is invalid."}); } return __VA_ARGS__; }} +@interface CustomImagePickerController : PSPDFImagePickerController +@end + +@implementation CustomImagePickerController + +- (PSPDFImageQuality)allowedImageQualities { + return PSPDFImageQualityLow; // This forces low. You can also return `PSPDFImageQualityAll` to allow the user to select the image quality. +} +@end + +@interface CustomButtonAnnotationToolbar : PSPDFAnnotationToolbar +@end + @interface RCTPSPDFKitView () @property (nonatomic, nullable) UIViewController *topController; @@ -25,16 +38,25 @@ @implementation RCTPSPDFKitView - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { - _pdfController = [[PSPDFViewController alloc] init]; + // Set configuration to use the custom annotation tool bar when initializing the PSPDFViewController. + // For more details, see `PSCCustomizeAnnotationToolbarExample.m` from PSPDFCatalog and our documentation here: https://pspdfkit.com/guides/ios/current/customizing-the-interface/customize-the-annotation-toolbar/ +// _pdfController = [[PSPDFViewController alloc] initWithDocument:nil configuration:[PSPDFConfiguration configurationWithBuilder:^(PSPDFConfigurationBuilder *builder) { +// [builder overrideClass:PSPDFAnnotationToolbar.class withClass:CustomButtonAnnotationToolbar.class]; +// }]]; + _pdfController.delegate = self; _pdfController.annotationToolbarController.delegate = self; + _pdfController = [[PSPDFViewController alloc] initWithDocument:nil configuration:[PSPDFConfiguration configurationWithBuilder:^(PSPDFConfigurationBuilder *builder) { + [builder overrideClass:PSPDFAnnotationToolbar.class withClass:CustomButtonAnnotationToolbar.class]; + [builder overrideClass:PSPDFImagePickerController.class withClass:CustomImagePickerController.class]; + }]]; _closeButton = [[UIBarButtonItem alloc] initWithImage:[PSPDFKitGlobal imageNamed:@"x"] style:UIBarButtonItemStylePlain target:self action:@selector(closeButtonPressed:)]; - - [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationChangedNotification object:nil]; - [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsAddedNotification object:nil]; - [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsRemovedNotification object:nil]; + + //[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationChangedNotification object:nil]; + //[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsAddedNotification object:nil]; + //[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsRemovedNotification object:nil]; } - + return self; } @@ -55,21 +77,21 @@ - (void)didMoveToWindow { if (controller == nil || self.window == nil || self.topController != nil) { return; } - + if (self.pdfController.configuration.useParentNavigationBar || self.hideNavigationBar) { self.topController = self.pdfController; - + } else { self.topController = [[PSPDFNavigationController alloc] initWithRootViewController:self.pdfController];; } - + UIView *topControllerView = self.topController.view; topControllerView.translatesAutoresizingMaskIntoConstraints = NO; - + [self addSubview:topControllerView]; [controller addChildViewController:self.topController]; [self.topController didMoveToParentViewController:controller]; - + [NSLayoutConstraint activateConstraints: @[[topControllerView.topAnchor constraintEqualToAnchor:self.topAnchor], [topControllerView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], @@ -88,7 +110,7 @@ - (void)destroyViewControllerRelationship { - (void)closeButtonPressed:(nullable id)sender { if (self.onCloseButtonPressed) { self.onCloseButtonPressed(@{}); - + } else { // try to be smart and pop if we are not displayed modally. BOOL shouldDismiss = YES; @@ -190,7 +212,7 @@ - (void)flexibleToolbarContainerDidHide:(PSPDFFlexibleToolbarContainer *)contain - (NSDictionary *> *)getAnnotations:(PSPDFPageIndex)pageIndex type:(PSPDFAnnotationType)type error:(NSError *_Nullable *)error { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, nil); - + NSArray *annotations = [document annotationsForPageAtIndex:pageIndex type:type]; NSArray *annotationsJSON = [RCTConvert instantJSONFromAnnotations:annotations error:error]; return @{@"annotations" : annotationsJSON}; @@ -206,11 +228,11 @@ - (BOOL)addAnnotation:(id)jsonAnnotation error:(NSError *_Nullable *)error { NSLog(@"Invalid JSON Annotation."); return NO; } - + PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, NO) PSPDFDocumentProvider *documentProvider = document.documentProviders.firstObject; - + BOOL success = NO; if (data) { PSPDFAnnotation *annotation = [PSPDFAnnotation annotationFromInstantJSON:data documentProvider:documentProvider error:error]; @@ -218,11 +240,11 @@ - (BOOL)addAnnotation:(id)jsonAnnotation error:(NSError *_Nullable *)error { success = [document addAnnotations:@[annotation] options:nil]; } } - + if (!success) { NSLog(@"Failed to add annotation."); } - + return success; } @@ -230,7 +252,7 @@ - (BOOL)removeAnnotationWithUUID:(NSString *)annotationUUID { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, NO) BOOL success = NO; - + NSArray *allAnnotations = [[document allAnnotationsOfType:PSPDFAnnotationTypeAll].allValues valueForKeyPath:@"@unionOfArrays.self"]; for (PSPDFAnnotation *annotation in allAnnotations) { // Remove the annotation if the uuids match. @@ -239,7 +261,7 @@ - (BOOL)removeAnnotationWithUUID:(NSString *)annotationUUID { break; } } - + if (!success) { NSLog(@"Failed to remove annotation."); } @@ -249,7 +271,7 @@ - (BOOL)removeAnnotationWithUUID:(NSString *)annotationUUID { - (NSDictionary *> *)getAllUnsavedAnnotationsWithError:(NSError *_Nullable *)error { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, nil) - + PSPDFDocumentProvider *documentProvider = document.documentProviders.firstObject; NSData *data = [document generateInstantJSONFromDocumentProvider:documentProvider error:error]; NSDictionary *annotationsJSON = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:error]; @@ -275,7 +297,7 @@ - (BOOL)addAnnotations:(id)jsonAnnotations error:(NSError *_Nullable *)error { NSLog(@"Invalid JSON Annotations."); return NO; } - + PSPDFDataContainerProvider *dataContainerProvider = [[PSPDFDataContainerProvider alloc] initWithData:data]; PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, NO) @@ -284,7 +306,7 @@ - (BOOL)addAnnotations:(id)jsonAnnotations error:(NSError *_Nullable *)error { if (!success) { NSLog(@"Failed to add annotations."); } - + [self.pdfController reloadPageAtIndex:self.pdfController.pageIndex animated:NO]; return success; } @@ -296,17 +318,17 @@ - (BOOL)addAnnotations:(id)jsonAnnotations error:(NSError *_Nullable *)error { NSLog(@"Invalid fully qualified name."); return nil; } - + PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, nil) - + for (PSPDFFormElement *formElement in document.formParser.forms) { if ([formElement.fullyQualifiedFieldName isEqualToString:fullyQualifiedName]) { id formFieldValue = formElement.value; return @{@"value": formFieldValue ?: [NSNull new]}; } } - + return @{@"error": @"Failed to get the form field value."}; } @@ -315,7 +337,7 @@ - (BOOL)setFormFieldValue:(NSString *)value fullyQualifiedName:(NSString *)fully NSLog(@"Invalid fully qualified name."); return NO; } - + PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, NO) @@ -364,7 +386,7 @@ - (void)annotationChangedNotification:(NSNotification *)notification { } return; } - + NSString *name = notification.name; NSString *change; if ([name isEqualToString:PSPDFAnnotationChangedNotification]) { @@ -374,7 +396,7 @@ - (void)annotationChangedNotification:(NSNotification *)notification { } else if ([name isEqualToString:PSPDFAnnotationsRemovedNotification]) { change = @"removed"; } - + NSArray *annotationsJSON = [RCTConvert instantJSONFromAnnotations:annotations error:NULL]; if (self.onAnnotationsChanged) { self.onAnnotationsChanged(@{@"change" : change, @"annotations" : annotationsJSON}); @@ -391,7 +413,7 @@ - (void)setLeftBarButtonItems:(nullable NSArray *)items forViewMode [leftItems addObject:barButtonItem]; } } - + if (viewMode.length) { [self.pdfController.navigationItem setLeftBarButtonItems:[leftItems copy] forViewMode:[RCTConvert PSPDFViewMode:viewMode] animated:animated]; } else { @@ -407,7 +429,7 @@ - (void)setRightBarButtonItems:(nullable NSArray *)items forViewMod [rightItems addObject:barButtonItem]; } } - + if (viewMode.length) { [self.pdfController.navigationItem setRightBarButtonItems:[rightItems copy] forViewMode:[RCTConvert PSPDFViewMode:viewMode] animated:animated]; } else { @@ -422,7 +444,7 @@ - (void)setRightBarButtonItems:(nullable NSArray *)items forViewMod } else { items = [self.pdfController.navigationItem leftBarButtonItems]; } - + return [self buttonItemsStringFromUIBarButtonItems:items]; } @@ -433,7 +455,7 @@ - (void)setRightBarButtonItems:(nullable NSArray *)items forViewMod } else { items = [self.pdfController.navigationItem rightBarButtonItems]; } - + return [self buttonItemsStringFromUIBarButtonItems:items]; } @@ -453,7 +475,7 @@ - (void)onStateChangedForPDFViewController:(PSPDFViewController *)pdfController break; } } - + self.onStateChanged(@{@"documentLoaded" : @(isDocumentLoaded), @"currentPageIndex" : @(pageIndex), @"pageCount" : @(pageCount), @@ -477,3 +499,47 @@ - (void)onStateChangedForPDFViewController:(PSPDFViewController *)pdfController } @end + +@implementation CustomButtonAnnotationToolbar + +/////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Lifecycle + +- (instancetype)initWithAnnotationStateManager:(PSPDFAnnotationStateManager *)annotationStateManager { + if ((self = [super initWithAnnotationStateManager:annotationStateManager])) { + PSPDFAnnotationGroupItem *freeText = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringFreeText]; + PSPDFAnnotationGroupItem *underline = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringUnderline]; + + PSPDFAnnotationGroupItem *inkPen = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringInk variant:PSPDFAnnotationVariantStringInkPen]; + PSPDFAnnotationGroupItem *inkHighlighter = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringInk variant:PSPDFAnnotationVariantStringInkHighlighter]; + + PSPDFAnnotationGroupItem *square = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringSquare]; + PSPDFAnnotationGroupItem *circle = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringCircle]; + PSPDFAnnotationGroupItem *line = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringLine]; + PSPDFAnnotationGroupItem *polygon = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringPolygon]; + PSPDFAnnotationGroupItem *polyline = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringPolyLine]; + + PSPDFAnnotationGroupItem *sound = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringSound]; + PSPDFAnnotationGroupItem *image = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringImage]; + PSPDFAnnotationGroupItem *link = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringLink]; + + PSPDFAnnotationGroupItem *eraser = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringEraser]; + PSPDFAnnotationGroupItem *note = [PSPDFAnnotationGroupItem itemWithType:PSPDFAnnotationStringNote]; + + + NSArray *compactGroups = @[[PSPDFAnnotationGroup groupWithItems:@[freeText, underline]], [PSPDFAnnotationGroup groupWithItems:@[inkPen, inkHighlighter]], [PSPDFAnnotationGroup groupWithItems:@[note, eraser]], [PSPDFAnnotationGroup groupWithItems:@[image, sound, link]], [PSPDFAnnotationGroup groupWithItems:@[square, circle, line, polygon, polyline]]]; + PSPDFAnnotationToolbarConfiguration *compact = [[PSPDFAnnotationToolbarConfiguration alloc] initWithAnnotationGroups:compactGroups]; + + NSArray *regularGroups = @[[PSPDFAnnotationGroup groupWithItems:@[freeText, underline]], [PSPDFAnnotationGroup groupWithItems:@[inkPen, inkHighlighter]], [PSPDFAnnotationGroup groupWithItems:@[note]], [PSPDFAnnotationGroup groupWithItems:@[eraser]], [PSPDFAnnotationGroup groupWithItems:@[image, sound, link]], [PSPDFAnnotationGroup groupWithItems:@[square, circle, line, polygon, polyline]]]; + PSPDFAnnotationToolbarConfiguration *regular = [[PSPDFAnnotationToolbarConfiguration alloc] initWithAnnotationGroups:regularGroups]; + + self.configurations = @[regular, compact]; + } + return self; +} + +- (void)dealloc { + [NSNotificationCenter.defaultCenter removeObserver:self]; +} + +@end