38
38
import com .facebook .react .uimanager .events .EventDispatcher ;
39
39
import com .pspdfkit .PSPDFKit ;
40
40
import com .pspdfkit .annotations .Annotation ;
41
+ import com .pspdfkit .annotations .AnnotationProvider ;
41
42
import com .pspdfkit .annotations .AnnotationType ;
42
43
import com .pspdfkit .annotations .configuration .AnnotationConfiguration ;
43
44
import com .pspdfkit .annotations .configuration .FreeTextAnnotationConfiguration ;
49
50
import com .pspdfkit .document .PdfDocument ;
50
51
import com .pspdfkit .document .PdfDocumentLoader ;
51
52
import com .pspdfkit .document .formatters .DocumentJsonFormatter ;
53
+ import com .pspdfkit .document .formatters .XfdfFormatter ;
54
+ import com .pspdfkit .document .providers .ContentResolverDataProvider ;
52
55
import com .pspdfkit .document .providers .DataProvider ;
56
+ import com .pspdfkit .exceptions .InvalidPasswordException ;
53
57
import com .pspdfkit .forms .ChoiceFormElement ;
54
58
import com .pspdfkit .forms .ComboBoxFormElement ;
55
59
import com .pspdfkit .forms .EditableButtonFormElement ;
60
+ import com .pspdfkit .forms .FormField ;
56
61
import com .pspdfkit .forms .TextFormElement ;
57
62
import com .pspdfkit .listeners .OnVisibilityChangedListener ;
58
63
import com .pspdfkit .listeners .SimpleDocumentListener ;
90
95
91
96
import java .io .ByteArrayOutputStream ;
92
97
import java .io .File ;
98
+ import java .io .FileNotFoundException ;
99
+ import java .io .OutputStream ;
93
100
import java .util .ArrayList ;
94
101
import java .util .Collections ;
95
102
import java .util .List ;
@@ -226,7 +233,7 @@ public void inject(FragmentManager fragmentManager, EventDispatcher eventDispatc
226
233
227
234
public void setFragmentTag (String fragmentTag ) {
228
235
this .fragmentTag = fragmentTag ;
229
- setupFragment ();
236
+ setupFragment (false );
230
237
}
231
238
232
239
public void setInitialConfiguration (PdfActivityConfiguration configuration ) {
@@ -253,7 +260,7 @@ public void setConfiguration(PdfActivityConfiguration configuration) {
253
260
removeFragment (false );
254
261
}
255
262
this .configuration = configuration ;
256
- setupFragment ();
263
+ setupFragment (false );
257
264
}
258
265
259
266
public PdfActivityConfiguration getConfiguration () {
@@ -271,7 +278,7 @@ public void setCustomToolbarItems(final ArrayList toolbarItems) {
271
278
272
279
public void setAnnotationConfiguration (final Map <AnnotationType ,AnnotationConfiguration > annotationsConfigurations ) {
273
280
this .annotationsConfigurations = annotationsConfigurations ;
274
- setupFragment ();
281
+ setupFragment (false );
275
282
}
276
283
277
284
public void setDocumentPassword (@ Nullable String documentPassword ) {
@@ -307,10 +314,10 @@ public void setDocument(@Nullable String documentPath) {
307
314
.observeOn (AndroidSchedulers .mainThread ())
308
315
.subscribe (imageDocument -> {
309
316
PdfView .this .document = imageDocument .getDocument ();
310
- setupFragment ();
317
+ setupFragment (false );
311
318
}, throwable -> {
312
319
PdfView .this .document = null ;
313
- setupFragment ();
320
+ setupFragment (false );
314
321
eventDispatcher .dispatchEvent (new PdfViewDocumentLoadFailedEvent (getId (), throwable .getMessage ()));
315
322
});
316
323
} else {
@@ -319,18 +326,21 @@ public void setDocument(@Nullable String documentPath) {
319
326
.observeOn (AndroidSchedulers .mainThread ())
320
327
.subscribe (pdfDocument -> {
321
328
PdfView .this .document = pdfDocument ;
322
- setupFragment ();
329
+ setupFragment (false );
323
330
}, throwable -> {
324
- PdfView .this .document = null ;
325
- setupFragment ();
326
- eventDispatcher .dispatchEvent (new PdfViewDocumentLoadFailedEvent (getId (), throwable .getMessage ()));
331
+ // The Android SDK will present password UI, do not emit an error.
332
+ if (!(throwable instanceof InvalidPasswordException )) {
333
+ PdfView .this .document = null ;
334
+ eventDispatcher .dispatchEvent (new PdfViewDocumentLoadFailedEvent (getId (), throwable .getMessage ()));
335
+ }
336
+ setupFragment (true );
327
337
});
328
338
}
329
339
}
330
340
331
341
public void setPageIndex (int pageIndex ) {
332
342
this .pageIndex = pageIndex ;
333
- setupFragment ();
343
+ setupFragment (false );
334
344
}
335
345
336
346
public void setDisableDefaultActionForTappedAnnotations (boolean disableDefaultActionForTappedAnnotations ) {
@@ -440,8 +450,8 @@ public void setHideDefaultToolbar(boolean hideDefaultToolbar) {
440
450
}));
441
451
}
442
452
443
- private void setupFragment () {
444
- if (fragmentTag != null && configuration != null && document != null ) {
453
+ private void setupFragment (boolean recreate ) {
454
+ if (fragmentTag != null && configuration != null && ( document != null || recreate == true ) ) {
445
455
PdfUiFragment pdfFragment = (PdfUiFragment ) fragmentManager .findFragmentByTag (fragmentTag );
446
456
if (pdfFragment != null &&
447
457
(pdfFragment .getArguments () == null ||
@@ -454,10 +464,16 @@ private void setupFragment() {
454
464
}
455
465
456
466
if (pdfFragment == null ) {
457
- pdfFragment = PdfUiFragmentBuilder .fromDocumentDescriptor (getContext (), DocumentDescriptor .fromDocument (document ))
467
+ if (recreate == true ) {
468
+ pdfFragment = PdfUiFragmentBuilder .fromUri (getContext (), Uri .parse (documentPath )).fragmentClass (ReactPdfUiFragment .class ).build ();
469
+ } else if (document != null ) {
470
+ pdfFragment = PdfUiFragmentBuilder .fromDocumentDescriptor (getContext (), DocumentDescriptor .fromDocument (document ))
458
471
.configuration (configuration )
459
472
.fragmentClass (ReactPdfUiFragment .class )
460
473
.build ();
474
+ } else {
475
+ return ;
476
+ }
461
477
// We put our internal id so we can track if this fragment belongs to us, used to handle orphaned fragments after hot reloads.
462
478
pdfFragment .getArguments ().putInt (ARG_ROOT_ID , internalId );
463
479
prepareFragment (pdfFragment , true );
@@ -710,8 +726,6 @@ public Single<List<Annotation>> getAllAnnotations(@Nullable final String type) {
710
726
.toList ();
711
727
}
712
728
713
-
714
-
715
729
public Disposable addAnnotation (final int requestId , ReadableMap annotation ) {
716
730
return getCurrentPdfFragment ().map (PdfFragment ::getDocument ).subscribeOn (Schedulers .io ())
717
731
.map (pdfDocument -> {
@@ -881,6 +895,65 @@ public Maybe<Boolean> setFormFieldValue(@NonNull String formElementName, @NonNul
881
895
});
882
896
}
883
897
898
+ public Disposable importXFDF (final int requestId , String filePath ) {
899
+
900
+ if (Uri .parse (filePath ).getScheme () == null ) {
901
+ filePath = FILE_SCHEME + filePath ;
902
+ }
903
+ if (fragment == null || fragment .getDocument () == null ) {
904
+ return null ;
905
+ }
906
+
907
+ return XfdfFormatter .parseXfdfAsync (fragment .getDocument (), new ContentResolverDataProvider (Uri .parse (filePath )))
908
+ .subscribeOn (Schedulers .io ())
909
+ .observeOn (AndroidSchedulers .mainThread ())
910
+ .subscribe (annotations -> {
911
+ for (Annotation annotation : annotations ) {
912
+ fragment .getDocument ().getAnnotationProvider ().addAnnotationToPage (annotation );
913
+ }
914
+ JSONObject result = new JSONObject ();
915
+ result .put ("success" , true );
916
+ eventDispatcher .dispatchEvent (new PdfViewDataReturnedEvent (getId (), requestId , result ));
917
+ }, throwable -> {
918
+ eventDispatcher .dispatchEvent (new PdfViewDataReturnedEvent (getId (), requestId , throwable ));
919
+ });
920
+ }
921
+
922
+ public Disposable exportXFDF (final int requestId , String filePath ) {
923
+
924
+ if (Uri .parse (filePath ).getScheme () == null ) {
925
+ filePath = FILE_SCHEME + filePath ;
926
+ }
927
+ if (fragment == null || fragment .getDocument () == null ) {
928
+ return null ;
929
+ }
930
+
931
+ try {
932
+ final OutputStream outputStream = getContext ().getContentResolver ().openOutputStream (Uri .parse (filePath ));
933
+ if (outputStream == null ) return null ;
934
+
935
+ List <Annotation > annotations = fragment .getDocument ().getAnnotationProvider ().getAllAnnotationsOfType (AnnotationProvider .ALL_ANNOTATION_TYPES );
936
+ List <FormField > formFields = fragment .getDocument ().getFormProvider ().getFormFields ();
937
+
938
+ String finalFilePath = filePath ;
939
+ return XfdfFormatter .writeXfdfAsync (fragment .getDocument (), annotations , formFields , outputStream )
940
+ .subscribeOn (Schedulers .io ())
941
+ .observeOn (AndroidSchedulers .mainThread ())
942
+ .subscribe (() -> {
943
+ JSONObject result = new JSONObject ();
944
+ result .put ("success" , true );
945
+ result .put ("filePath" , finalFilePath );
946
+ eventDispatcher .dispatchEvent (new PdfViewDataReturnedEvent (getId (), requestId , result ));
947
+ }, throwable -> {
948
+ eventDispatcher .dispatchEvent (new PdfViewDataReturnedEvent (getId (), requestId , throwable ));
949
+ }
950
+ );
951
+ } catch (final FileNotFoundException ignored ) {
952
+ eventDispatcher .dispatchEvent (new PdfViewDataReturnedEvent (getId (), requestId , ignored ));
953
+ }
954
+ return null ;
955
+ }
956
+
884
957
public JSONObject convertConfiguration () {
885
958
try {
886
959
JSONObject config = new JSONObject ();
0 commit comments