Skip to content

Commit e60da0e

Browse files
committed
Release 4.2.0
1 parent 9eeb915 commit e60da0e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2520
-3379
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 4.2.0 — 11 Feb 2026
2+
3+
- Removes the deprecated Annotation APIs from the `NutrientView` namespace, since they are available on `PDFDocument`. (J#HYB-945)
4+
- Adds the `enterContentEditingMode` API to `NutrientView` to enter content editing mode programmatically. (J#HYB-943)
5+
- Adds the `CONTENT_EDITING_BUTTON_ITEM` option to the list of available Toolbar buttons. (J#HYB-943)
6+
- Updates for Nutrient Android SDK 11.0.0.
7+
18
## 4.1.0 — 30 Jan 2026
29

310
- Adds the `updateAnnotations` API to `PDFDocument` to update existing annotation properties. (J#HYB-828)

__tests__/pdfdocument.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ jest.mock('react-native', () => {
66
};
77
});
88

9+
jest.mock('../src/ArchitectureDetector', () => ({
10+
isNewArchitectureEnabled: jest.fn(),
11+
}));
12+
913
import { PDFDocument } from '../src/document/PDFDocument';
14+
import { isNewArchitectureEnabled } from '../src/ArchitectureDetector';
1015
import { NativeModules, findNodeHandle } from 'react-native';
1116
import {
1217
ButtonFormElement,
@@ -28,16 +33,27 @@ describe('PDFDocument JS helpers', () => {
2833
beforeEach(() => {
2934
jest.clearAllMocks();
3035
(findNodeHandle as jest.Mock).mockReturnValue(999);
36+
(isNewArchitectureEnabled as jest.Mock).mockReturnValue(false);
3137
});
3238

33-
test('getRef returns numeric reference when findNodeHandle returns null (Fabric fallback)', () => {
39+
test('getRef returns numeric reference on Fabric (pdfViewRef is component id)', () => {
40+
(isNewArchitectureEnabled as jest.Mock).mockReturnValue(true);
3441
(findNodeHandle as jest.Mock).mockReturnValue(null);
3542
const doc = new PDFDocument(1234);
3643
// @ts-ignore access private
3744
const ref = (doc as any).getRef();
3845
expect(ref).toBe(1234);
3946
});
4047

48+
test('getRef returns null on Paper when findNodeHandle returns null (no fallback)', () => {
49+
(isNewArchitectureEnabled as jest.Mock).mockReturnValue(false);
50+
(findNodeHandle as jest.Mock).mockReturnValue(null);
51+
const doc = new PDFDocument(1234);
52+
// @ts-ignore access private
53+
const ref = (doc as any).getRef();
54+
expect(ref).toBeNull();
55+
});
56+
4157
test('setPageIndex rejects out of bounds', async () => {
4258
const doc = new PDFDocument(5);
4359
(NativeModules.PDFDocumentManager.getPageCount as jest.Mock).mockResolvedValueOnce(3);

android/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Contains gradle configuration constants
1616
*/
1717
ext {
18-
NUTRIENT_VERSION = '10.10.1'
18+
NUTRIENT_VERSION = '11.0.0'
1919
}
2020

2121
buildscript {
@@ -146,6 +146,9 @@ dependencies {
146146

147147
implementation "androidx.recyclerview:recyclerview:1.4.0"
148148

149+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
150+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx3:1.7.3"
151+
149152
// Explicitly declare Compose Foundation to ensure version 1.9.4 (matches PSPDFKit SDK)
150153
implementation "androidx.compose.foundation:foundation:1.9.4"
151154

android/src/main/java/com/pspdfkit/react/PDFDocumentModule.kt

Lines changed: 316 additions & 228 deletions
Large diffs are not rendered by default.

android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java

Lines changed: 23 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -65,31 +65,19 @@ public class ReactPdfViewManager extends ViewGroupManager<PdfView> {
6565

6666
public static final int COMMAND_ENTER_ANNOTATION_CREATION_MODE = 1;
6767
public static final int COMMAND_EXIT_CURRENTLY_ACTIVE_MODE = 2;
68-
public static final int COMMAND_SAVE_CURRENT_DOCUMENT = 3;
69-
public static final int COMMAND_GET_ANNOTATIONS = 4;
70-
public static final int COMMAND_ADD_ANNOTATION = 5;
71-
public static final int COMMAND_GET_ALL_UNSAVED_ANNOTATIONS = 6;
72-
public static final int COMMAND_ADD_ANNOTATIONS = 7;
73-
public static final int COMMAND_GET_FORM_FIELD_VALUE = 8;
74-
public static final int COMMAND_SET_FORM_FIELD_VALUE = 9;
75-
public static final int COMMAND_GET_ALL_ANNOTATIONS = 11;
76-
public static final int COMMAND_REMOVE_ANNOTATION = 10;
77-
public static final int COMMAND_REMOVE_FRAGMENT = 12;
78-
public static final int COMMAND_SET_TOOLBAR_MENU_ITEMS = 13;
79-
public static final int COMMAND_REMOVE_ANNOTATIONS = 14;
80-
public static final int COMMAND_GET_CONFIGURATION = 18;
81-
public static final int COMMAND_SET_TOOLBAR = 19;
82-
public static final int COMMAND_SET_MEASUREMENT_VALUE_CONFIGURATIONS = 21;
83-
public static final int COMMAND_GET_MEASUREMENT_VALUE_CONFIGURATIONS = 22;
84-
public static final int COMMAND_IMPORT_XFDF = 23;
85-
public static final int COMMAND_EXPORT_XFDF = 24;
86-
public static final int COMMAND_SET_ANNOTATION_FLAGS = 25;
87-
public static final int COMMAND_GET_ANNOTATION_FLAGS = 26;
88-
public static final int COMMAND_CLEAR_SELECTED_ANNOTATIONS = 27;
89-
public static final int COMMAND_SELECT_ANNOTATIONS = 28;
90-
public static final int COMMAND_SET_PAGE_INDEX = 29;
91-
public static final int COMMAND_SET_EXCLUDED_ANNOTATIONS = 30;
92-
public static final int COMMAND_SET_USER_INTERFACE_VISIBLE = 31;
68+
public static final int COMMAND_ENTER_CONTENT_EDITING_MODE = 3;
69+
public static final int COMMAND_SAVE_CURRENT_DOCUMENT = 4;
70+
public static final int COMMAND_GET_FORM_FIELD_VALUE = 5;
71+
public static final int COMMAND_SET_FORM_FIELD_VALUE = 6;
72+
public static final int COMMAND_REMOVE_FRAGMENT = 7;
73+
public static final int COMMAND_SET_TOOLBAR_MENU_ITEMS = 8;
74+
public static final int COMMAND_GET_CONFIGURATION = 9;
75+
public static final int COMMAND_SET_TOOLBAR = 10;
76+
public static final int COMMAND_SET_MEASUREMENT_VALUE_CONFIGURATIONS = 11;
77+
public static final int COMMAND_GET_MEASUREMENT_VALUE_CONFIGURATIONS = 12;
78+
public static final int COMMAND_SET_PAGE_INDEX = 13;
79+
public static final int COMMAND_SET_EXCLUDED_ANNOTATIONS = 14;
80+
public static final int COMMAND_SET_USER_INTERFACE_VISIBLE = 15;
9381

9482
private final CompositeDisposable annotationDisposables = new CompositeDisposable();
9583

@@ -129,28 +117,16 @@ public Map<String, Integer> getCommandsMap() {
129117
Map<String, Integer> commandMap = MapBuilder.of();
130118
commandMap.put("enterAnnotationCreationMode", COMMAND_ENTER_ANNOTATION_CREATION_MODE);
131119
commandMap.put("exitCurrentlyActiveMode", COMMAND_EXIT_CURRENTLY_ACTIVE_MODE);
120+
commandMap.put("enterContentEditingMode", COMMAND_ENTER_CONTENT_EDITING_MODE);
132121
commandMap.put("saveCurrentDocument", COMMAND_SAVE_CURRENT_DOCUMENT);
133-
commandMap.put("getAnnotations", COMMAND_GET_ANNOTATIONS);
134-
commandMap.put("addAnnotation", COMMAND_ADD_ANNOTATION);
135-
commandMap.put("getAllUnsavedAnnotations", COMMAND_GET_ALL_UNSAVED_ANNOTATIONS);
136-
commandMap.put("addAnnotations", COMMAND_ADD_ANNOTATIONS);
137122
commandMap.put("getFormFieldValue", COMMAND_GET_FORM_FIELD_VALUE);
138123
commandMap.put("setFormFieldValue", COMMAND_SET_FORM_FIELD_VALUE);
139-
commandMap.put("removeAnnotation", COMMAND_REMOVE_ANNOTATION);
140-
commandMap.put("removeAnnotations", COMMAND_REMOVE_ANNOTATIONS);
141-
commandMap.put("getAllAnnotations", COMMAND_GET_ALL_ANNOTATIONS);
142124
commandMap.put("removeFragment", COMMAND_REMOVE_FRAGMENT);
143125
commandMap.put("setToolbarMenuItems", COMMAND_SET_TOOLBAR_MENU_ITEMS);
144126
commandMap.put("setMeasurementValueConfigurations", COMMAND_SET_MEASUREMENT_VALUE_CONFIGURATIONS);
145127
commandMap.put("getMeasurementValueConfigurations", COMMAND_GET_MEASUREMENT_VALUE_CONFIGURATIONS);
146128
commandMap.put("getConfiguration", COMMAND_GET_CONFIGURATION);
147129
commandMap.put("setToolbar", COMMAND_SET_TOOLBAR);
148-
commandMap.put("importXFDF", COMMAND_IMPORT_XFDF);
149-
commandMap.put("exportXFDF", COMMAND_EXPORT_XFDF);
150-
commandMap.put("setAnnotationFlags", COMMAND_SET_ANNOTATION_FLAGS);
151-
commandMap.put("getAnnotationFlags", COMMAND_GET_ANNOTATION_FLAGS);
152-
commandMap.put("clearSelectedAnnotations", COMMAND_CLEAR_SELECTED_ANNOTATIONS);
153-
commandMap.put("selectAnnotations", COMMAND_SELECT_ANNOTATIONS);
154130
commandMap.put("setPageIndex", COMMAND_SET_PAGE_INDEX);
155131
commandMap.put("setExcludedAnnotations", COMMAND_SET_EXCLUDED_ANNOTATIONS);
156132
commandMap.put("setUserInterfaceVisible", COMMAND_SET_USER_INTERFACE_VISIBLE);
@@ -326,6 +302,15 @@ public void receiveCommand(@NonNull final PdfView root, int commandId, @Nullable
326302
}
327303
}
328304
break;
305+
case COMMAND_ENTER_CONTENT_EDITING_MODE:
306+
if (args != null) {
307+
final int requestIdContent = args.getInt(0);
308+
root.enterContentEditingMode(
309+
() -> root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestIdContent, true)),
310+
(Consumer<Throwable>) throwable -> root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestIdContent, throwable))
311+
);
312+
}
313+
break;
329314
case COMMAND_EXIT_CURRENTLY_ACTIVE_MODE:
330315
if (args != null) {
331316
final int requestId = args.getInt(0);
@@ -346,86 +331,6 @@ public void receiveCommand(@NonNull final PdfView root, int commandId, @Nullable
346331
}
347332
}
348333
break;
349-
case COMMAND_GET_ANNOTATIONS:
350-
if (args != null) {
351-
final int requestId = args.getInt(0);
352-
Disposable annotationDisposable = root.getAnnotations(args.getInt(1), args.getString(2))
353-
.subscribeOn(Schedulers.io())
354-
.observeOn(AndroidSchedulers.mainThread())
355-
.subscribe(new Consumer<List<Annotation>>() {
356-
@Override
357-
public void accept(List<Annotation> annotations) {
358-
root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, annotations));
359-
}
360-
});
361-
annotationDisposables.add(annotationDisposable);
362-
}
363-
break;
364-
case COMMAND_GET_ALL_ANNOTATIONS:
365-
if (args != null && args.size() == 2) {
366-
final int requestId = args.getInt(0);
367-
annotationDisposables.add(root.getAllAnnotations(args.getString(1))
368-
.subscribeOn(Schedulers.io())
369-
.observeOn(AndroidSchedulers.mainThread())
370-
.subscribe(annotations -> {
371-
root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, annotations));
372-
}, throwable -> {
373-
root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, throwable));
374-
}));
375-
}
376-
break;
377-
case COMMAND_ADD_ANNOTATION:
378-
if (args != null && args.size() == 2) {
379-
final int requestId = args.getInt(0);
380-
annotationDisposables.add(root.addAnnotation(requestId, args.getMap(1)));
381-
}
382-
break;
383-
case COMMAND_REMOVE_ANNOTATION:
384-
if (args != null && args.size() == 2) {
385-
final int requestId = args.getInt(0);
386-
annotationDisposables.add(root.removeAnnotation(requestId, args.getMap(1)));
387-
}
388-
break;
389-
case COMMAND_REMOVE_ANNOTATIONS:
390-
if(args != null && args.size() == 2) {
391-
final int requestId = args.getInt(0);
392-
final ReadableArray annotations = args.getArray(1);
393-
final int length = annotations.size();
394-
for (int i = 0; i < length; i++) {
395-
ReadableMap annotation = annotations.getMap(i);
396-
annotationDisposables.add(root.removeAnnotation(requestId, annotation));
397-
}
398-
}
399-
break;
400-
case COMMAND_GET_ALL_UNSAVED_ANNOTATIONS:
401-
if (args != null) {
402-
final int requestId = args.getInt(0);
403-
Disposable annotationDisposable = root.getAllUnsavedAnnotations()
404-
.subscribeOn(Schedulers.io())
405-
.observeOn(AndroidSchedulers.mainThread())
406-
.subscribe(jsonObject -> root.getEventDispatcher()
407-
.dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, jsonObject)));
408-
annotationDisposables.add(annotationDisposable);
409-
}
410-
break;
411-
case COMMAND_ADD_ANNOTATIONS:
412-
if (args != null && args.size() == 2) {
413-
final int requestId = args.getInt(0);
414-
annotationDisposables.add(root.addAnnotations(requestId, args.getMap(1)));
415-
}
416-
break;
417-
case COMMAND_SET_ANNOTATION_FLAGS:
418-
if (args != null && args.size() == 3) {
419-
final int requestId = args.getInt(0);
420-
annotationDisposables.add(root.setAnnotationFlags(requestId, args.getString(1), args.getArray(2)));
421-
}
422-
break;
423-
case COMMAND_GET_ANNOTATION_FLAGS:
424-
if (args != null && args.size() == 2) {
425-
final int requestId = args.getInt(0);
426-
annotationDisposables.add(root.getAnnotationFlags(requestId, args.getString(1)));
427-
}
428-
break;
429334
case COMMAND_GET_FORM_FIELD_VALUE:
430335
if (args != null && args.size() == 2) {
431336
final int requestId = args.getInt(0);
@@ -493,41 +398,6 @@ public void accept(List<Annotation> annotations) {
493398
setToolbar(root,args.getMap(0));
494399
}
495400
break;
496-
case COMMAND_IMPORT_XFDF:
497-
if (args != null && args.size() == 2) {
498-
final int requestId = args.getInt(0);
499-
root.importXFDF(requestId, args.getString(1));
500-
}
501-
break;
502-
case COMMAND_EXPORT_XFDF:
503-
if (args != null && args.size() == 2) {
504-
final int requestId = args.getInt(0);
505-
root.exportXFDF(requestId, args.getString(1));
506-
}
507-
break;
508-
case COMMAND_CLEAR_SELECTED_ANNOTATIONS:
509-
if (args != null) {
510-
final int requestId = args.getInt(0);
511-
try {
512-
root.clearSelectedAnnotations();
513-
JSONObject result = new JSONObject();
514-
result.put("success", true);
515-
root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, result));
516-
} catch (Exception e) {
517-
root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, e));
518-
}
519-
}
520-
break;
521-
case COMMAND_SELECT_ANNOTATIONS:
522-
if (args != null && args.size() == 3) {
523-
final int requestId = args.getInt(0);
524-
try {
525-
root.selectAnnotations(requestId, args.getArray(1), args.getBoolean(2));
526-
} catch (Exception e) {
527-
root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, e));
528-
}
529-
}
530-
break;
531401
case COMMAND_SET_PAGE_INDEX:
532402
if (args != null && args.size() == 1) {
533403
try {

android/src/main/java/com/pspdfkit/react/ToolbarMenuItemsAdapter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class ToolbarMenuItemsAdapter {
3030
private static final String TOOLBAR_ITEM_ANNOTATION_LIST = "annotationListButtonItem";
3131
private static final String TOOLBAR_ITEM_AI_ASSISTANT = "aiAssistantButtonItem";
3232
private static final String TOOLBAR_ITEM_READER_VIEW = "readerViewButtonItem";
33+
private static final String TOOLBAR_ITEM_CONTENT_EDITING = "contentEditingButtonItem";
3334

3435
private final PdfActivityConfiguration.Builder newConfigurations;
3536

@@ -69,6 +70,9 @@ public ToolbarMenuItemsAdapter(@NonNull final PdfActivityConfiguration currentCo
6970
case TOOLBAR_ITEM_READER_VIEW:
7071
configuration.enableReaderView(true);
7172
break;
73+
case TOOLBAR_ITEM_CONTENT_EDITING:
74+
configuration.contentEditingEnabled(true);
75+
break;
7276
}
7377
}
7478
newConfigurations = configuration;

android/src/main/java/com/pspdfkit/react/common/NutrientPropsToolbarHelper.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ public static void applyToolbar(@NonNull final PdfView view, @NonNull ReadableMa
3030
for (int i = 0; i < buttons.size(); i++) {
3131
Object item = buttons.get(i);
3232
if (item instanceof String) {
33-
stockToolbarItems.pushString((String) item);
33+
String stockItem = (String) item;
34+
// On Android, documentEditorButtonItem should behave like thumbnailsButtonItem.
35+
if ("documentEditorButtonItem".equals(stockItem)) {
36+
stockItem = "thumbnailsButtonItem";
37+
}
38+
stockToolbarItems.pushString(stockItem);
3439
} else if (item instanceof HashMap) {
3540
((HashMap<String, Integer>) item).put("index", i);
3641
customToolbarItems.add(item);

0 commit comments

Comments
 (0)