/react-native-pdftron-engage

react-native-pdftron-simple

Primary LanguageObjective-COtherNOASSERTION

PDFTron React Native Wrapper

Prerequisites

  • No license key is required for trial. However, a valid commercial license key is required after trial.
  • npm or yarn
  • PDFTron SDK >= 6.10.0
  • react-native >= 0.60.0 (for versions before 0.60.0, use branch rn553)

Preview

Android iOS
demo demo

Installation

  1. If using yarn, do: yarn global add react-native-cli

  2. First, follow the official getting started guide on setting up the React Native environment, setting up the iOS environment, setting up the Android environment, and creating a React Native project, the following steps will assume your app is created through react-native init MyApp.

  3. In MyApp folder, install react-native-pdftron by calling:

    yarn add github:PDFTron/pdftron-react-native
    yarn add @react-native-community/cli --dev
    yarn add @react-native-community/cli-platform-android --dev
    yarn add @react-native-community/cli-platform-ios --dev
    yarn install

    or

    npm install github:PDFTron/pdftron-react-native --save
    npm install @react-native-community/cli --save-dev
    npm install @react-native-community/cli-platform-android --save-dev
    npm install @react-native-community/cli-platform-ios --save-dev

Android

  1. Add the following in your android/app/build.gradle file:

    android {
        compileSdkVersion rootProject.ext.compileSdkVersion
    
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    
        defaultConfig {
            applicationId "com.reactnativesample"
            minSdkVersion rootProject.ext.minSdkVersion
            targetSdkVersion rootProject.ext.targetSdkVersion
            versionCode 1
            versionName "1.0"
    +       multiDexEnabled true
        }
    
        dependencies {
    +       implementation "androidx.multidex:multidex:2.0.1"
        }
    
        ...
    }
  2. Add the following to your android/app/src/main/AndroidManifest.xml file:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.myapp">
        
    	<uses-permission android:name="android.permission.INTERNET" />
    	<!-- Required to read and write documents from device storage -->
    +	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    	<!-- Required if you want to record audio annotations -->
    +	<uses-permission android:name="android.permission.RECORD_AUDIO" />
    
      <application
        ...
    +   android:largeHeap="true"
    +   android:usesCleartextTraffic="true">
    
        <activity
          android:name=".MainActivity"
          android:label="@string/app_name"
          android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
    -     android:windowSoftInputMode="adjustResize"
    +     android:windowSoftInputMode="adjustPan"
    +     android:theme="@style/CustomAppTheme">
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
        </activity>
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
      </application>
    </manifest>
  3. In your android\app\src\main\java\com\myapp\MainApplication.java file, change Application to MultiDexApplication:

    - import android.app.Application;
    + import androidx.multidex.MultiDexApplication;
    ...
    - public class MainApplication extends Application implements ReactApplication {
    + public class MainApplication extends MultiDexApplication implements ReactApplication {
  4. Replace App.js with what is shown here

  5. Finally in the root project directory, run react-native run-android.

iOS

  1. Open Podfile in the ios folder, add:

    target 'MyApp' do
        use_frameworks!
        pod 'PDFNet', podspec: 'https://www.pdftron.com/downloads/ios/cocoapods/pdfnet/latest.podspec'
        pod 'RNPdftron', :path => '../node_modules/react-native-pdftron'
    end
    
  2. In the ios folder, run pod install.

  3. (Optional) If you need a close button icon, you will need to add the PNG resources to MyApp as well, i.e. ic_close_black_24px.

  4. Replace App.js with what is shown here.

  5. Finally in the root project directory, run react-native run-ios.

Usage

Replace App.js with the following:

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  PermissionsAndroid,
  BackHandler,
  NativeModules,
  Alert
} from 'react-native';

import { DocumentView, RNPdftron } from 'react-native-pdftron';

type Props = {};
export default class App extends Component<Props> {

  constructor(props) {
    super(props);

    this.state = {
      permissionGranted: Platform.OS === 'ios' ? true : false
    };

    RNPdftron.initialize("Insert commercial license key here after purchase");
    RNPdftron.enableJavaScript(true);
  }

  componentDidMount() {
    if (Platform.OS === 'android') {
      this.requestStoragePermission();
    }
  }

  async requestStoragePermission() {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        this.setState({
          permissionGranted: true
        });
        console.log("Storage permission granted");
      } else {
        this.setState({
          permissionGranted: false
        });
        console.log("Storage permission denied");
      }
    } catch (err) {
      console.warn(err);
    }
  }

  onLeadingNavButtonPressed = () => {
    console.log('leading nav button pressed');
    if (Platform.OS === 'ios') {
      Alert.alert(
        'App',
        'onLeadingNavButtonPressed',
        [
          {text: 'OK', onPress: () => console.log('OK Pressed')},
        ],
        { cancelable: true }
      )
    } else {
      BackHandler.exitApp();
    }
  }

  render() {
    if (!this.state.permissionGranted) {
      return (
        <View style={styles.container}>
          <Text>
            Storage permission required.
          </Text>
        </View>
      )
    }

    const path = "https://pdftron.s3.amazonaws.com/downloads/pl/PDFTRON_mobile_about.pdf";

    return (
      <DocumentView
        document={path}
        showLeadingNavButton={true}
        leadingNavButtonIcon={Platform.OS === 'ios' ? 'ic_close_black_24px.png' : 'ic_arrow_back_white_24dp'}
        onLeadingNavButtonPressed={this.onLeadingNavButtonPressed}
      />
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  }
});
  • (iOS) For app bundle file path:
document="sample"
  • (Android) For local storage file path:
document="file:///storage/emulated/0/Download/sample.pdf"
  • (Android) For raw resource path (include file extension):
document="android.resource://mypackagename/raw/sample.pdf"
  • (Android) For content Uri:
document="content://..."

API

RNPdftron

initialize

initialize(string)

enableJavaScript

enableJavaScript(bool)

encryptDocument

encryptDocument(string, string, string, Promise)

This function does not lock around the document so be sure to not use it while the document is opened in the viewer.

Example:

RNPdftron.encryptDocument("/sdcard/Download/new.pdf", "1111", "").then(() => {
  console.log("done password");
});

Parameters:

Name Type Description
file path string the local file path to the file
password string the password
current password string the current password, use empty string if no password

Components

DocumentView

A component for displaying documents of different types such as PDF, docx, pptx, xlsx and various image formats.

Props

document

string, required

password

string, optional

leadingNavButtonIcon

string, optional

onLeadingNavButtonPressed

function, optional

showLeadingNavButton

bool, optional

onDocumentLoaded

function, optional

onDocumentError

function, optional

disabledElements

array of string, optional

disabledTools

array of string, optional

customHeaders

object, optional

readOnly

bool, optional, default to false

thumbnailViewEditingEnabled

bool, optional, default to true

annotationAuthor

string, optional

continuousAnnotationEditing

bool, optional

fitMode

string, optional

layoutMode

string, optional

initialPageNumber

number, optional

pageNumber

number, optional

onPageChanged

function, optional

onZoomChanged

function, optional

Perameters:

Name Type Description
previousPageNumber int the previous page number
pageNumber int the current page number
topToolbarEnabled

bool, optional

bottomToolbarEnabled

bool, optional

pageIndicatorEnabled

bool, optional

showSavedSignatures

bool, optional

isBase64String

bool, optional If true, document prop will be treated as a base64 string.

padStatusBar

bool, optional, android only If true, the viewer will add padding to take account of status bar. Default to false.

autoSaveEnabled

bool, optional

annotationMenuItems

array of Config.AnnotationMenu string constants, optional

pageChangeOnTap

bool, optional, default to true

collabEnabled

bool, optional, if set to true then currentUser must be set as well for collaboration mode to work

currentUser

string, required if collabEnabled is set to true

currentUserName

string, optional

onExportAnnotationCommand

function, optional, annotation command will only be given if collabEnabled is set to true

onAnnotationChanged

function, optional

Parameters:

Name Type Description
action string the action that occurred (add, delete, modify)
annotations array array of annotation data in the format {id: string, pageNumber: int}

Example:

import { DocumentView, Config } from 'react-native-pdftron';
<DocumentView
  ref={(c) => this._viewer = c}
  document={path}
  showLeadingNavButton={true}
  leadingNavButtonIcon={Platform.OS === 'ios' ? 'ic_close_black_24px.png' : 'ic_arrow_back_white_24dp'}
  onLeadingNavButtonPressed={() => {}}
  onDocumentLoaded={() => {}}
  onDocumentError={() => {}}
  disabledElements={[Config.Buttons.searchButton, Config.Buttons.shareButton]}
  disabledTools={[Config.Tools.annotationCreateLine, Config.Tools.annotationCreateRectangle]}
  customHeaders={{Foo: bar}}
  initialPageNumber={11}
  readOnly={false}
  annotationAuthor={'PDFTron'}
  continuousAnnotationEditing={true}
  fitMode={Config.FitMode.FitPage}
  layoutMode={Config.LayoutMode.Continuous}
  onPageChanged={({previousPageNumber, pageNumber}) => { console.log('page changed'); }}
  onAnnotationChanged={({action, annotations}) => { console.log('annotations changed'); }}
/>

Methods

setToolMode

To set the current tool mode (Config.Tools constants).

this._viewer.setToolMode(Config.Tools.annotationCreateFreeHand);
commitTool

Commits the current tool, only available for multi-stroke ink and poly-shape.

Returns a Promise.

this._viewer.commitTool().then((committed) => {
  // committed: true if either ink or poly-shape tool is committed, false otherwise
});
getPageCount

To get the current page count of the document.

Returns a Promise.

this._viewer.getPageCount().then((pageCount) => {
  console.log('pageCount', pageCount);
});
importAnnotations

To import XFDF string to the current document.

Returns a Promise.

const xfdf = '<?xml version="1.0" encoding="UTF-8"?>\n<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">...</xfdf>';
this._viewer.importAnnotations(xfdf);
exportAnnotations

To extract XFDF from the current document.

Perameters:

Name Type Description
options object key: annotList, type: array

Returns a Promise.

this._viewer.exportAnnotations().then((xfdf) => {
  console.log('xfdf', xfdf);
});

With options:

// annotList is an array of annotation data in the format {id: string, pageNumber: int}
this._viewer.exportAnnotations({annotList: annotations}).then((xfdf) => {
  console.log('xfdf for annotations', xfdf);
});
flattenAnnotations

To flatten the forms and (optionally) annotations in the current document. The formsOnly parameter controls whether only forms are flattened.

Returns a Promise.

// flatten forms and annotations in the current document.
this._viewer.flattenAnnotations(false);
saveDocument

To save the current document.

Returns a Promise.

this._viewer.saveDocument().then((filePath) => {
  console.log('saveDocument:', filePath);
});
setFlagForFields

Set a field flag value on one or more form fields.

Parameters:

Name Type Description
fields array list of field names for which the flag should be set
flag integer flag to be set (see https://www.pdftron.com/api/ios/Enums/PTFieldFlag.html)
value bool value to set for flag

Returns a Promise.

this._viewer.setFlagForFields(['First Name', 'Last Name'], Config.FieldFlags.ReadOnly, true);
setValueForFields

Set field values on one or more form fields.

Parameters:

Name Type Description
fieldsMap object map of field names and values which should be set

Returns a Promise.

this._viewer.setValueForFields({
  'textField1': 'Test',
  'textField2': 1234,
  'checkboxField1': true,
  'checkboxField2': false,
  'radioButton1': 'Yes',
  'radioButton2': 'No'
});
importAnnotationCommand

This is used only if collabEnabled is set to true. Import remote annotation command to local document.

Parameters:

Name Type Description
xfdfCommand string the XFDF command string
initialLoad bool whether this is for initial load

Returns a Promise.

Contributing

See Contributing

License

See License