UNPKG

@nutrient-sdk/react-native

Version:
1,324 lines (1,205 loc) 106 kB
// Copyright © 2018-2025 PSPDFKit GmbH d/b/a Nutrient. 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 PSPDFKIT LICENSE AGREEMENT. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. // This notice may not be removed from this file. // import PropTypes from 'prop-types'; import * as React from 'react'; import { findNodeHandle, NativeModules, Platform, requireNativeComponent, UIManager, } from 'react-native'; /** * NutrientView is a React Native component used to view PDF documents on iOS and Android. * @augments {React.Component<Props, *>} * @hideconstructor * @example * <NutrientView * document={DOCUMENT_PATH} * configuration={{ * showThumbnailBar: PDFConfiguration.ShowThumbnailBar.SCROLLABLE, * pageTransition: PDFConfiguration.PageTransition.SCROLL_CONTINUOUS, * scrollDirection: PDFConfiguration.ScrollDirection.VERTICAL, * }} * ref={this.pdfRef} * fragmentTag="PDF1" * style={{ flex: 1 }} * /> */ class NutrientView extends React.Component { // Cache architecture detection and Fabric component to avoid work on every render static _isNewArchitecture = null; static _FabricComponent = null; static _getArchitectureInfo() { if (this._isNewArchitecture === null) { const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); this._isNewArchitecture = isNewArchitectureEnabled(); if (this._isNewArchitecture) { try { // Require from src/ so Metro can process codegen for NutrientViewNativeComponent this._FabricComponent = require('./src/NutrientViewFabric').default; } catch (error) { console.error('[Nutrient] Failed to load Fabric component:', error); this._isNewArchitecture = false; // Fallback to Paper this._FabricComponent = null; } } } return { isNewArchitecture: this._isNewArchitecture, FabricComponent: this._FabricComponent }; } /** * @ignore */ refs; /** * @ignore */ _nextRequestId = 1; /** * @ignore */ _requestMap = new Map(); /** * @ignore */ _pdfDocument = null; /** * @ignore */ _notificationCenter = null; /** * @ignore */ _componentRef = React.createRef(this); // Fabric ref used only in New Architecture to forward imperative methods _fabricRef = React.createRef(); render() { // Architecture detection - use cached result to decide Fabric vs Paper const { isNewArchitecture, FabricComponent } = NutrientView._getArchitectureInfo(); if (isNewArchitecture && FabricComponent) { return React.createElement(FabricComponent, { ...this.props, ref: this._fabricRef }); } if (Platform.OS === 'ios' || Platform.OS === 'android') { const onCloseButtonPressedHandler = this.props.onCloseButtonPressed ? event => { this.props.onCloseButtonPressed(event.nativeEvent); } : null; if (Platform.OS === 'android') { // Android: Only group document and configuration for proper ordering const { document, configuration, // Explicitly exclude document and configuration from otherProps ...otherProps } = this.props; // Only create combined prop for document and configuration const documentAndConfiguration = { document: document !== undefined ? document : null, configuration: configuration !== undefined ? configuration : null, }; return ( <RCTPSPDFKitView ref={this._componentRef} documentAndConfiguration={documentAndConfiguration} // Android only fragmentTag="NutrientView.FragmentTag" {...otherProps} onCloseButtonPressed={onCloseButtonPressedHandler} onStateChanged={this._onStateChanged} onDocumentSaved={this._onDocumentSaved} onDocumentLoaded={this._onDocumentLoaded} onDocumentSaveFailed={this._onDocumentSaveFailed} onDocumentLoadFailed={this._onDocumentLoadFailed} onAnnotationTapped={this._onAnnotationTapped} onAnnotationsChanged={this._onAnnotationsChanged} onNavigationButtonClicked={this._onNavigationButtonClicked} onDataReturned={this._onDataReturned} onCustomToolbarButtonTapped={this._onCustomToolbarButtonTapped} onCustomAnnotationContextualMenuItemTapped={ this._onCustomAnnotationContextualMenuItemTapped } onReady={this._onReady} /> ); } else { // iOS: Use original approach with individual props return ( <RCTPSPDFKitView ref={this._componentRef} fragmentTag="NutrientView.FragmentTag" {...this.props} onCloseButtonPressed={onCloseButtonPressedHandler} onStateChanged={this._onStateChanged} onDocumentSaved={this._onDocumentSaved} onDocumentLoaded={this._onDocumentLoaded} onDocumentSaveFailed={this._onDocumentSaveFailed} onDocumentLoadFailed={this._onDocumentLoadFailed} onAnnotationTapped={this._onAnnotationTapped} onAnnotationsChanged={this._onAnnotationsChanged} onNavigationButtonClicked={this._onNavigationButtonClicked} onDataReturned={this._onDataReturned} onCustomToolbarButtonTapped={this._onCustomToolbarButtonTapped} onCustomAnnotationContextualMenuItemTapped={ this._onCustomAnnotationContextualMenuItemTapped } onReady={this._onReady} /> ); } } else { return null; } } /** * @ignore */ _onStateChanged = event => { if (this.props.onStateChanged) { this.props.onStateChanged(event.nativeEvent); } }; /** * @ignore */ _onDocumentLoaded = event => { if (this.props.onDocumentLoaded) { this.props.onDocumentLoaded(event.nativeEvent); } }; /** * @ignore */ _onDocumentSaved = event => { if (this.props.onDocumentSaved) { this.props.onDocumentSaved(event.nativeEvent); } }; /** * @ignore */ _onDocumentSaveFailed = event => { if (this.props.onDocumentSaveFailed) { this.props.onDocumentSaveFailed(event.nativeEvent); } }; /** * @ignore */ _onDocumentLoadFailed = event => { if (this.props.onDocumentLoadFailed) { this.props.onDocumentLoadFailed(event.nativeEvent); } }; /** * @ignore */ _onAnnotationTapped = event => { if (this.props.onAnnotationTapped) { this.props.onAnnotationTapped(event.nativeEvent); } }; /** * @ignore */ _onAnnotationsChanged = event => { if (this.props.onAnnotationsChanged) { this.props.onAnnotationsChanged(event.nativeEvent); } }; /** * @ignore */ _onNavigationButtonClicked = event => { if (this.props.onNavigationButtonClicked) { this.props.onNavigationButtonClicked(event.nativeEvent); } }; /** * @ignore */ _onDataReturned = event => { let { requestId, result, error } = event.nativeEvent; let promise = this._requestMap[requestId]; if (result !== undefined) { promise.resolve(result); } else { promise.reject(error); } this._requestMap.delete(requestId); }; /** * @ignore */ _onCustomToolbarButtonTapped = event => { if (this.props.onCustomToolbarButtonTapped) { this.props.onCustomToolbarButtonTapped(event.nativeEvent); } }; /** * @ignore */ _onCustomAnnotationContextualMenuItemTapped = event => { if (this.props.onCustomAnnotationContextualMenuItemTapped) { this.props.onCustomAnnotationContextualMenuItemTapped(event.nativeEvent); } }; /** * @ignore */ _onReady = event => { if (this.props.onReady) { this.props.onReady(event.nativeEvent); } }; /** * Enters annotation creation mode, showing the annotation creation toolbar. * @method enterAnnotationCreationMode * @param { Annotation.Type } [annotationType] The annotation type that should be pre-selected when entering annotation creation mode. * @example * this.pdfRef.current.enterAnnotationCreationMode(); * @memberof NutrientView */ enterAnnotationCreationMode = function (annotationType) { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.enterAnnotationCreationMode(annotationType); } if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .enterAnnotationCreationMode, [requestId, annotationType], ); } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.enterAnnotationCreationMode( annotationType, findNodeHandle(this._componentRef.current), ); } }; /** * Exits the currently active mode, hiding all toolbars. * @method exitCurrentlyActiveMode * @example * this.pdfRef.current.exitCurrentlyActiveMode(); * @memberof NutrientView */ exitCurrentlyActiveMode = function () { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.exitCurrentlyActiveMode(); } if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .exitCurrentlyActiveMode, [requestId], ); } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.exitCurrentlyActiveMode( findNodeHandle(this._componentRef.current), ); } }; /** * Saves the document that's currently open. * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().save()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.save|save()}. * @method saveCurrentDocument * @memberof NutrientView * @example * const result = await this.pdfRef.current.saveCurrentDocument(); * * @returns { Promise<boolean> } A promise resolving to ```true``` if the document was saved, and ```false``` if not. */ saveCurrentDocument = function () { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.saveCurrentDocument(); } if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .saveCurrentDocument, [requestId], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.saveCurrentDocument( findNodeHandle(this._componentRef.current), ); } }; /** * Get the current PDF document. * @method getDocument * @example * const document = this.pdfRef.current?.getDocument(); * @see {@link https://nutrient.io/api/react-native/PDFDocument.html} for available methods. * @memberof NutrientView * @returns { PDFDocument } A reference to the document that is currently loaded in the NutrientView component. */ getDocument () { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component ref return this._fabricRef.current?.getDocument(); } if (this._pdfDocument == null) { this._pdfDocument = new PDFDocument(this._componentRef.current); return this._pdfDocument; } else { return this._pdfDocument; } }; /** * Get the current Notification Center. * @method getNotificationCenter * @example * const document = this.pdfRef.current?.getNotificationCenter(); * @see {@link https://nutrient.io/api/react-native/NotificationCenter.html} for available methods. * @memberof NutrientView * @returns { NotificationCenter } A reference to the Notification Center that can be used to subscribe and unsubscribe from events. */ getNotificationCenter () { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component ref return this._fabricRef.current?.getNotificationCenter(); } if (this._notificationCenter == null) { this._notificationCenter = new NotificationCenter(this._componentRef.current); return this._notificationCenter; } else { return this._notificationCenter; } }; /** * @method clearSelectedAnnotations * @memberof NutrientView * @description Clears all currently selected Annotations. * @example * const result = await this.pdfRef.current?.clearSelectedAnnotations(); * @returns { Promise<any> } A promise containing the result of the operation. ```true``` if the annotations selection were cleared, ```false``` otherwise. */ clearSelectedAnnotations = function () { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.clearSelectedAnnotations(); } if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .clearSelectedAnnotations, [requestId], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.clearSelectedAnnotations( findNodeHandle(this._componentRef.current), ); } }; /** * @method selectAnnotations * @memberof NutrientView * @param { object } annotations An array of the annotations to select in Instant JSON format. * @param { boolean } [showContextualMenu] Whether the annotation contextual menu should be shown after selection. * @description Select one or more annotations. * @example * const result = await this.pdfRef.current?.selectAnnotations(annotations); * @returns { Promise<boolean> } A promise containing the result of the operation. ```true``` if the annotations were selected, ```false``` otherwise. */ selectAnnotations = function (annotations, showContextualMenu = false) { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.selectAnnotations(annotations, showContextualMenu); } if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .selectAnnotations, [requestId, annotations, showContextualMenu], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.selectAnnotations( annotations, showContextualMenu, findNodeHandle(this._componentRef.current), ); } }; /** * Gets all annotations of the given type from the specified page. * * @method getAnnotations * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().getAnnotations()``` or ```getAnnotationsForPage()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.getAnnotations|getAnnotations()} and {@link https://nutrient.io/api/react-native/PDFDocument.html#.getAnnotationsForPage|getAnnotationsForPage()}. * @memberof NutrientView * @param { number } pageIndex The page index to get the annotations for, starting at 0. * @param { string } [type] The type of annotations to get. If not specified or ```null```, all annotation types will be returned. * @example * const result = await this.pdfRef.current.getAnnotations(3, 'pspdfkit/ink'); * @see {@link https://nutrient.io/guides/web/json/schema/annotations/} for supported types. * * @returns { Promise } A promise containing an object with an array of InstantJSON objects. */ getAnnotations = function (pageIndex, type) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands.getAnnotations, [requestId, pageIndex, type], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getAnnotations( pageIndex, type, findNodeHandle(this._componentRef.current), ); } }; /** * Adds a new annotation to the current document. * * @method addAnnotation * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().addAnnotations()``` instead. * @memberof NutrientView * @param { object } annotation The InstantJSON of the annotation to add. * @example * const result = await this.pdfRef.current.addAnnotation(annotationJSON); * @see {@link https://nutrient.io/guides/web/json/schema/annotations/} for document JSON structure. * * @returns { Promise<boolean> } A promise resolving to ```true``` if the annotation was added successfully, and ```false``` if an error occurred. */ addAnnotation = function (annotation) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands.addAnnotation, [requestId, annotation], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.addAnnotation( annotation, findNodeHandle(this._componentRef.current), ); } }; /** * Removes an existing annotation from the current document. * * @method removeAnnotation * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().removeAnnotations()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.removeAnnotations|removeAnnotations()}. * @memberof NutrientView * @param { object } annotation The InstantJSON of the annotation to remove. * @example * const result = await this.pdfRef.current.removeAnnotation(instantJSON); * * @returns { Promise } A promise resolving to ```true``` if the annotation was removed successfully, and ```false``` if the annotation couldn't be found or an error occurred. */ removeAnnotation = function (annotation) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands.removeAnnotation, [requestId, annotation], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.removeAnnotation( annotation, findNodeHandle(this._componentRef.current), ); } }; /** * Removes the supplied document InstantJSON from the current document. * * @method removeAnnotations * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().removeAnnotations()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.removeAnnotations|removeAnnotations()}. * @memberof NutrientView * @param { object } annotation The InstantJSON of the annotations to remove. * @example * const result = await this.pdfRef.current.removeAnnotations(instantJSON); * * @returns { Promise } A promise resolving to ```true``` if the annotations were removed successfully, and ```false``` if the annotations couldn't be found or an error occurred. */ removeAnnotations = function (annotations) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .removeAnnotations, [requestId, annotations], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.removeAnnotations( annotations, findNodeHandle(this._componentRef.current), ); } }; /** * Gets all unsaved changes to annotations. * * @method getAllUnsavedAnnotations * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().getAllUnsavedAnnotations()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.getAllUnsavedAnnotations|getAllUnsavedAnnotations()}. * @memberof NutrientView * @returns { Promise } A promise containing document InstantJSON. * @see {@link https://nutrient.io/guides/android/current/importing-exporting/instant-json/#instant-document-json-api-a56628} for more information. */ getAllUnsavedAnnotations = function () { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .getAllUnsavedAnnotations, [requestId], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getAllUnsavedAnnotations( findNodeHandle(this._componentRef.current), ); } }; /** * Gets all annotations of the given type. * * @method getAllAnnotations * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().getAnnotations()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.getAnnotations|getAnnotations()}. * @memberof NutrientView * @param { string } [type] The type of annotations to get. If not specified or ```null```, all annotation types will be returned. * @see {@link https://nutrient.io/guides/web/json/schema/annotations/} for supported types. * @example * const result = await this.pdfRef.current.getAllAnnotations('all'); * // result: {'annotations' : [instantJson]} * * @returns { Promise } A promise containing an object with an array of InstantJSON objects. */ getAllAnnotations = function (type) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .getAllAnnotations, [requestId, type], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getAllAnnotations( type, findNodeHandle(this._componentRef.current), ); } }; /** * Applies the supplied document InstantJSON to the current document. * * @method addAnnotations * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().addAnnotations()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.addAnnotations|addAnnotations()}. * @memberof NutrientView * @param { object } annotations The document InstantJSON to apply to the current document. * @example * const result = await this.pdfRef.current.addAnnotations(annotationsJSON); * @see {@link https://nutrient.io/guides/web/json/schema/annotations/} for document JSON structure. * * @returns { Promise<boolean> } A promise resolving to ```true``` if the annotations were added successfully, and ```false``` if an error occurred. */ addAnnotations = function (annotations) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands.addAnnotations, [requestId, annotations], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.addAnnotations( annotations, findNodeHandle(this._componentRef.current), ); } }; /** * Sets the flags of the specified annotation. * * @method setAnnotationFlags * @memberof NutrientView * @param { string } uuid The UUID of the annotation to update. * @param { Annotation.Flags[] } flags The flags to apply to the annotation. * @deprecated Since Nutrient React Native SDK 4.0. Use ```this.pdfRef.current?.getDocument().setAnnotationFlags()``` instead. * @example * const result = await this.pdfRef.current.setAnnotationFlags('bb61b1bf-eacd-4227-a5bf-db205e591f5a', ['locked', 'hidden']); * * @returns { Promise<boolean> } A promise resolving to ```true``` if the annotations were added successfully, and ```false``` if an error occurred. */ setAnnotationFlags = function (uuid, flags) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .setAnnotationFlags, [requestId, uuid, flags], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.setAnnotationFlags( uuid, flags, findNodeHandle(this._componentRef.current), ); } }; /** * Gets the flags for the specified annotation. * * @method getAnnotationFlags * @memberof NutrientView * @param { string } uuid The UUID of the annotation to query. * @deprecated Since Nutrient React Native SDK 4.0. Use ```this.pdfRef.current?.getDocument().getAnnotationFlags()``` instead. * @example * const flags = await this.pdfRef.current.getAnnotationFlags('bb61b1bf-eacd-4227-a5bf-db205e591f5a'); * * @returns { Promise<Annotation.Flags[]> } A promise containing the flags of the specified annotation. */ getAnnotationFlags = function (uuid) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .getAnnotationFlags, [requestId, uuid], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getAnnotationFlags( uuid, findNodeHandle(this._componentRef.current), ); } }; /** * Imports the supplied XFDF file into the current document. * * @method importXFDF * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().importXFDF()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.importXFDF|importXFDF()}. * @memberof NutrientView * @param { string } filePath The path to the XFDF file to import. * @example * const result = await this.pdfRef.current.importXFDF('path/to/XFDF.xfdf'); * * @returns { Promise<any> } A promise containing an object with the result. ```true``` if the xfdf file was imported successfully, and ```false``` if an error occurred. */ importXFDF = function (filePath) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands.importXFDF, [requestId, filePath], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.importXFDF( filePath, findNodeHandle(this._componentRef.current), ); } }; /** * Exports the annotations from the current document to a XFDF file. * * @method exportXFDF * @deprecated Since Nutrient React Native SDK 2.12. Use ```this.pdfRef.current?.getDocument().exportXFDF()``` instead. * See {@link https://nutrient.io/api/react-native/PDFDocument.html#.exportXFDF|exportXFDF()}. * @memberof NutrientView * @param { string } filePath The path where the XFDF file should be exported to. * @example * const result = await this.pdfRef.current.exportXFDF('path/to/XFDF.xfdf'); * * @returns { Promise<any> } A promise containing an object with the exported file path and result. ```true``` if the xfdf file was exported successfully, and ```false``` if an error occurred. */ exportXFDF = function (filePath) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands.exportXFDF, [requestId, filePath], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.exportXFDF( filePath, findNodeHandle(this._componentRef.current), ); } }; /** * @typedef FormFieldResult * @property { string } [formElement] The form field value * @property { string } [error] The error description */ /** * Gets the form field value of the supplied form field name. * * @method getFormFieldValue * @memberof NutrientView * @param { string } fullyQualifiedName The fully qualified name of the form element. * @deprecated Since Nutrient React Native SDK 2.17. Use the ```getFormElements``` API on the ```PDFDocument.forms``` object instead, and filter by ```fullyQualifiedFieldName```. * @example * const result = await this.pdfRef.current.getFormFieldValue('myFormElement'); * // result: {'myFormElement' : value} * // or * // {'error' : 'Failed to get the form field value.'} * * @returns { Promise<FormFieldResult> } A promise containing an object with the value, or an error if the form field could not be found. */ getFormFieldValue = function (fullyQualifiedName) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .getFormFieldValue, [requestId, fullyQualifiedName], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getFormFieldValue( fullyQualifiedName, findNodeHandle(this._componentRef.current), ); } }; /** * Sets the form field value of the supplied form field name. * * @method setFormFieldValue * @memberof NutrientView * @param { string } fullyQualifiedName The fully qualified name of the form element. When using form elements such as radio buttons, the individual elements can be accessed by appending the index to the fully qualified name, for example ```choiceElement.0``` and ```choiceElement.1```. * @param { string } value The new string value of the form element. For button form elements, pass ```selected``` or ```deselected```. For choice form elements, pass the index of the choice to select, for example ```1```. * @deprecated Since Nutrient React Native SDK 2.17. Use one of the ```update``` APIs on the ```PDFDocument.forms``` object instead. * @example * const result = await this.pdfRef.current.setFormFieldValue('Name_Last', 'Appleseed'); * * @returns { Promise<boolean> } A promise resolving to ```true``` if the value was set successfully, and ```false``` if an error occurred. */ setFormFieldValue = function (fullyQualifiedName, value) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .setFormFieldValue, [requestId, fullyQualifiedName, value], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.setFormFieldValue( value, fullyQualifiedName, findNodeHandle(this._componentRef.current), ); } }; /** * Sets the left bar button items for the specified view mode. * Note: The same button item cannot be added to both the left and right bar button items simultaneously. * * @method setLeftBarButtonItems * @memberof NutrientView * @param { Array<string> } items The list of bar button items. * @deprecated Since Nutrient React Native SDK 4.0. Use ```this.pdfRef.current?.setToolbar()``` instead. * @see {@link https://github.com/PSPDFKit/react-native/blob/master/ios/Converters/RCTConvert+UIBarButtonItem.m} for supported button items. * @param { string } [viewMode] The view mode for which the bar buttons should be set. Options are: ```document```, ```thumbnails```, ```documentEditor```, or ```null```. If ```null``` is passed, the bar button items for all the view modes are set. * @param { boolean } [animated] Specifies whether changing the bar buttons should be animated. * @example * const result = await this.pdfRef.current.setLeftBarButtonItems( * ['searchButtonItem', 'thumbnailsButtonItem'], * 'document', * true); * */ setLeftBarButtonItems = function (items, viewMode, animated) { if (Platform.OS === 'ios') { NativeModules.PSPDFKitViewManager.setLeftBarButtonItems( items, viewMode, animated, findNodeHandle(this._componentRef.current), ); } }; /** * Gets the left bar button items for the specified view mode. * * @method getLeftBarButtonItemsForViewMode * @memberof NutrientView * @param { string } [viewMode] The view mode to query. Options are: ```document```, ```thumbnails```, ```documentEditor```, or ```null```. If ```null``` is passed, the bar button items for the current view mode are returned. * @deprecated Since Nutrient React Native SDK 4.0. Use ```this.pdfRef.current?.getToolbar()``` instead. * @returns { Promise<Array<string>> } A promise containing an array of bar button items, or an error if the items couldn't be retrieved. * @example * const leftBarButtonItems = await this.pdfRef.current.getLeftBarButtonItemsForViewMode('document'); * // leftBarButtonItems: ['outlineButtonItem', 'searchButtonItem'] * // or * // {'error' : 'Failed to get the left bar button items.'} * */ getLeftBarButtonItemsForViewMode = function (viewMode) { if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getLeftBarButtonItemsForViewMode( viewMode, findNodeHandle(this._componentRef.current), ); } }; /** * Sets the right bar button items for the specified view mode. * Note: The same button item cannot be added to both the left and right bar button items simultaneously. * * @method setRightBarButtonItems * @memberof NutrientView * @param { Array<string> } items The list of bar button items. * @deprecated Since Nutrient React Native SDK 4.0. Use ```this.pdfRef.current?.setToolbar()``` instead. * @see {@link https://github.com/PSPDFKit/react-native/blob/master/ios/Converters/RCTConvert+UIBarButtonItem.m} for supported button items. * @param { string } [viewMode] The view mode for which the bar buttons should be set. Options are: ```document```, ```thumbnails```, ```documentEditor```, or ```null```. If ```null``` is passed, the bar button items for all the view modes are set. * @param { boolean } [animated] Specifies whether changing the bar buttons should be animated. * @example * const result = await this.pdfRef.current.setRightBarButtonItems( * ['searchButtonItem', 'thumbnailsButtonItem'], * 'document', * true); * */ setRightBarButtonItems = function (items, viewMode, animated) { if (Platform.OS === 'ios') { NativeModules.PSPDFKitViewManager.setRightBarButtonItems( items, viewMode, animated, findNodeHandle(this._componentRef.current), ); } }; /** * Gets the right bar button items for the specified view mode. * * @method getRightBarButtonItemsForViewMode * @memberof NutrientView * @param { string } [viewMode] The view mode to query. Options are: ```document```, ```thumbnails```, ```documentEditor```, or ```null```. If ```null``` is passed, the bar button items for the current view mode are returned. * @deprecated Since Nutrient React Native SDK 4.0. Use ```this.pdfRef.current?.getToolbar()``` instead. * @returns { Promise<Array<string>> } A promise containing an array of bar button items, or an error if the items couldn't be retrieved. * @example * const rightBarButtonItems = await this.pdfRef.current.getRightBarButtonItemsForViewMode('document'); * // rightBarButtonItems: ['outlineButtonItem', 'searchButtonItem'] * // or * // {'error' : 'Failed to get the right bar button items.'} * */ getRightBarButtonItemsForViewMode = function (viewMode) { if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getRightBarButtonItemsForViewMode( viewMode, findNodeHandle(this._componentRef.current), ); } }; /** * Sets the Toolbar object to customize the toolbar appearance and behaviour. * * @method setToolbar * @memberof NutrientView * @param { Toolbar } toolbar The toolbar object. * @example * const toolbar = { * // iOS * rightBarButtonItems: { * viewMode: Toolbar.PDFViewMode.VIEW_MODE_DOCUMENT, * animated: true, * buttons: ['searchButtonItem', 'readerViewButtonItem'] * }, * // Android * toolbarMenuItems: { * buttons: ['searchButtonItem', 'readerViewButtonItem'] * }, * } * this.pdfRef.current.setToolbar(toolbar); * */ setToolbar = function (toolbar) { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.setToolbar(toolbar); } if (Platform.OS === 'ios') { NativeModules.PSPDFKitViewManager.setToolbar( toolbar, findNodeHandle(this._componentRef.current), ); } else if (Platform.OS === 'android') { UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands.setToolbar, [toolbar], ); } }; /** * Gets the toolbar for the specified view mode. * * @method getToolbar * @memberof NutrientView * @param { string } [viewMode] The view mode to query. Options are: ```document```, ```thumbnails```, ```documentEditor```, or ```null```. If ```null``` is passed, the toolbar buttons for the current view mode are returned. * * @returns { Promise<Array<string>> } A promise containing the toolbar object, or an error if it couldn't be retrieved. * @example * const toolbar = await this.pdfRef.current.getToolbar('document'); * */ getToolbar = function (viewMode) { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.getToolbar(viewMode); } if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getToolbar( viewMode, findNodeHandle(this._componentRef.current), ); } }; /** * Sets the measurement value configurations for the ```NutrientView```. * * @method setMeasurementValueConfigurations * @memberof NutrientView * @param { MeasurementValueConfiguration[] } configurations The array of ```MeasurementValueConfiguration``` objects that should be applied to the document. * @returns { Promise<boolean> } A promise containing the result of the operation. * @example * const scale: MeasurementScale = { * unitFrom: Measurements.ScaleUnitFrom.INCH, * valueFrom: 1.0, * unitTo: Measurements.ScaleUnitTo.INCH, * valueTo: 2.54 * }; * * const measurementValueConfig: MeasurementValueConfiguration = { * name: 'Custom Scale', * scale: scale, * precision: Measurements.Precision.FOUR_DP * }; * * const configs = [measurementValueConfig]; * await this.pdfRef.current?.setMeasurementValueConfigurations(configs); */ setMeasurementValueConfigurations = function (configurations) { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.setMeasurementValueConfigurations(configurations); } if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .setMeasurementValueConfigurations, [requestId, configurations], ); return promise; } NativeModules.PSPDFKitViewManager.setMeasurementValueConfigurations( configurations, findNodeHandle(this._componentRef.current), ); }; /** * Gets the current NutrientView MeasurementValueConfigurations. * * @method getMeasurementValueConfigurations * @memberof NutrientView * * @returns { Promise<MeasurementValueConfiguration[]> } A promise containing an array of ```MeasurementValueConfiguration``` objects. * @example * const configurations = await this.pdfRef.current.getMeasurementValueConfigurations(); */ getMeasurementValueConfigurations = function () { // Architecture detection via helper function const { isNewArchitectureEnabled } = require('./lib/ArchitectureDetector'); if (isNewArchitectureEnabled()) { // Delegate to Fabric component return this._fabricRef.current?.getMeasurementValueConfigurations(); } if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); UIManager.dispatchViewManagerCommand( findNodeHandle(this._componentRef.current), this._getViewManagerConfig('RCTPSPDFKitView').Commands .getMeasurementValueConfigurations, [requestId], ); return promise; } else if (Platform.OS === 'ios') { return NativeModules.PSPDFKitViewManager.getMeasurementValueConfigurations( findNodeHandle(this._componentRef.current), ); } }; /** * Customizes the visible toolbar menu items for Android. * * @method setToolbarMenuItems * @memberof NutrientView * @param { Array<string> } toolbarMenuI