Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add form read/write API #107

Merged
merged 3 commits into from
Aug 7, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class ReactPdfViewManager extends ViewGroupManager<PdfView> {
public static final int COMMAND_ADD_ANNOTATION = 5;
public static final int COMMAND_GET_ALL_UNSAVED_ANNOTATIONS = 6;
public static final int COMMAND_ADD_ANNOTATIONS = 7;
public static final int COMMAND_GET_FORM_FIELD_VALUE = 8;
public static final int COMMAND_SET_FORM_FIELD_VALUE = 9;

private CompositeDisposable annotationDisposables = new CompositeDisposable();

Expand Down Expand Up @@ -77,7 +79,7 @@ public void onDropViewInstance(PdfView view) {
@Nullable
@Override
public Map<String, Integer> getCommandsMap() {
return MapBuilder.of(
Map<String, Integer> commandMap = MapBuilder.of(
"enterAnnotationCreationMode",
COMMAND_ENTER_ANNOTATION_CREATION_MODE,
"exitCurrentlyActiveMode",
Expand All @@ -92,6 +94,9 @@ public Map<String, Integer> getCommandsMap() {
COMMAND_GET_ALL_UNSAVED_ANNOTATIONS,
"addAnnotations",
COMMAND_ADD_ANNOTATIONS);
commandMap.put("getFormFieldValue", COMMAND_GET_FORM_FIELD_VALUE);
commandMap.put("setFormFieldValue", COMMAND_SET_FORM_FIELD_VALUE);
return commandMap;
}

@ReactProp(name = "fragmentTag")
Expand Down Expand Up @@ -189,10 +194,21 @@ public void accept(JSONObject jsonObject) {
}
break;
case COMMAND_ADD_ANNOTATIONS:
if (args != null) {
if (args != null && args.size() == 1) {
root.addAnnotations(args.getMap(0));
}
break;
case COMMAND_GET_FORM_FIELD_VALUE:
if (args != null && args.size() == 2) {
final int requestId = args.getInt(0);
annotationDisposables.add(root.getFormFieldValue(requestId, args.getString(1)));
}
break;
case COMMAND_SET_FORM_FIELD_VALUE:
if (args != null && args.size() == 2) {
annotationDisposables.add(root.setFormFieldValue(args.getString(0), args.getString(1)));
}
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.pspdfkit.react.events;

import android.support.annotation.IdRes;
import android.support.annotation.NonNull;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
Expand Down Expand Up @@ -41,7 +42,7 @@ public PdfViewDataReturnedEvent(@IdRes int viewId, int requestId, List<Annotatio
payload = Arguments.makeNativeMap(map);
}

public PdfViewDataReturnedEvent(@IdRes int viewId, int requestId, JSONObject jsonObject) {
public PdfViewDataReturnedEvent(@IdRes int viewId, int requestId, @NonNull JSONObject jsonObject) {
super(viewId);
Map<String, Object> map = new HashMap<>();
map.put("requestId", requestId);
Expand All @@ -55,6 +56,14 @@ public PdfViewDataReturnedEvent(@IdRes int viewId, int requestId, JSONObject jso
payload = Arguments.makeNativeMap(map);
}

public PdfViewDataReturnedEvent(@IdRes int viewId, int requestId, @NonNull Throwable throwable) {
super(viewId);

payload = Arguments.createMap();
payload.putInt("requestId", requestId);
payload.putString("error", throwable.getMessage());
}

@Override
public String getEventName() {
return EVENT_NAME;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public static Map<String, Object> jsonObjectToMap(JSONObject object) throws JSON
value = toList((JSONArray) value);
} else if (value instanceof JSONObject) {
value = jsonObjectToMap((JSONObject) value);
} else if ( value == JSONObject.NULL) {
value = null;
}
map.put(key, value);
}
Expand All @@ -41,6 +43,8 @@ private static List<Object> toList(JSONArray array) throws JSONException {
value = toList((JSONArray) value);
} else if (value instanceof JSONObject) {
value = jsonObjectToMap((JSONObject) value);
} else if ( value == JSONObject.NULL) {
value = null;
}
list.add(value);
}
Expand Down
109 changes: 106 additions & 3 deletions android/src/main/java/com/pspdfkit/views/PdfView.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@
import com.pspdfkit.document.PdfDocument;
import com.pspdfkit.document.formatters.DocumentJsonFormatter;
import com.pspdfkit.document.providers.DataProvider;
import com.pspdfkit.forms.ChoiceFormElement;
import com.pspdfkit.forms.ComboBoxFormElement;
import com.pspdfkit.forms.EditableButtonFormElement;
import com.pspdfkit.forms.FormElement;
import com.pspdfkit.forms.TextFormElement;
import com.pspdfkit.listeners.SimpleDocumentListener;
import com.pspdfkit.react.R;
import com.pspdfkit.react.events.PdfViewDataReturnedEvent;
import com.pspdfkit.react.events.PdfViewDocumentSaveFailedEvent;
import com.pspdfkit.react.events.PdfViewDocumentSavedEvent;
import com.pspdfkit.react.events.PdfViewStateChangedEvent;
Expand All @@ -36,7 +42,7 @@
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.Callable;
Expand Down Expand Up @@ -344,8 +350,8 @@ public void saveCurrentDocument() {
eventDispatcher.dispatchEvent(new PdfViewDocumentSaveFailedEvent(getId(), e.getMessage()));
}
}
}
}

public Single<List<Annotation>> getAnnotations(int pageIndex, @Nullable String type) {
return fragment.getDocument().getAnnotationProvider().getAllAnnotationsOfType(getTypeFromString(type), pageIndex, 1)
.toList();
Expand Down Expand Up @@ -420,6 +426,103 @@ public void addAnnotations(ReadableMap annotation) {
JSONObject json = new JSONObject(annotation.toHashMap());
final DataProvider dataProvider = new DocumentJsonDataProvider(json);
DocumentJsonFormatter.importDocumentJson(fragment.getDocument(), dataProvider);
}

public Disposable getFormFieldValue(final int requestId, @NonNull String formElementName) {
return document.getFormProvider().getFormElementWithNameAsync(formElementName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<FormElement>() {
@Override
public void accept(FormElement formElement) throws Exception {
JSONObject result = new JSONObject();
if (formElement instanceof TextFormElement) {
TextFormElement textFormElement = (TextFormElement) formElement;
String text = textFormElement.getText();
if (text == null || text.isEmpty()) {
result.put("value", JSONObject.NULL);
} else {
result.put("value", text);
}
} else if (formElement instanceof EditableButtonFormElement) {
EditableButtonFormElement editableButtonFormElement = (EditableButtonFormElement) formElement;
if (editableButtonFormElement.isSelected()) {
result.put("value", "selected");
} else {
result.put("value", "deselected");
}
} else if (formElement instanceof ComboBoxFormElement) {
ComboBoxFormElement comboBoxFormElement = (ComboBoxFormElement) formElement;
if (comboBoxFormElement.isCustomTextSet()) {
result.put("value", comboBoxFormElement.getCustomText());
} else {
result.put("value", comboBoxFormElement.getSelectedIndexes());
}
} else if (formElement instanceof ChoiceFormElement) {
result.put("value", ((ChoiceFormElement) formElement).getSelectedIndexes());
}

if (result.length() == 0) {
// No type was applicable.
result.put("error", "Unsupported form field encountered");
eventDispatcher.dispatchEvent(new PdfViewDataReturnedEvent(getId(), requestId, result));
} else {
eventDispatcher.dispatchEvent(new PdfViewDataReturnedEvent(getId(), requestId, result));
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
eventDispatcher.dispatchEvent(new PdfViewDataReturnedEvent(getId(), requestId, throwable));
}
}, new Action() {
@Override
public void run() {
try {
JSONObject result = new JSONObject();
result.put("error", "Failed to get the form field value.");
eventDispatcher.dispatchEvent(new PdfViewDataReturnedEvent(getId(), requestId, result));
} catch (Exception e) {
eventDispatcher.dispatchEvent(new PdfViewDataReturnedEvent(getId(), requestId, e));
}
}
});

}

public Disposable setFormFieldValue(@NonNull String formElementName, @NonNull final String value) {
return document.getFormProvider().getFormElementWithNameAsync(formElementName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<FormElement>() {

@Override
public void accept(FormElement formElement) {
if (formElement instanceof TextFormElement) {
TextFormElement textFormElement = (TextFormElement) formElement;
textFormElement.setText(value);
} else if (formElement instanceof EditableButtonFormElement) {
EditableButtonFormElement editableButtonFormElement = (EditableButtonFormElement) formElement;
if (value.equalsIgnoreCase("selected")) {
editableButtonFormElement.select();
} else if (value.equalsIgnoreCase("deselected")) {
editableButtonFormElement.deselect();
}
} else if (formElement instanceof ChoiceFormElement) {
ChoiceFormElement choiceFormElement = (ChoiceFormElement) formElement;
try {
int selectedIndex = Integer.parseInt(value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about multi-selectable choice fields?

List<Integer> selectedIndices = new ArrayList<>();
selectedIndices.add(selectedIndex);
choiceFormElement.setSelectedIndexes(selectedIndices);
} catch (NumberFormatException e) {
// This isn't an index maybe we can set a custom value on a combobox.
if (formElement instanceof ComboBoxFormElement) {
((ComboBoxFormElement) formElement).setCustomText(value);
}
}
}
}
});
}
}
64 changes: 56 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ class PSPDFKitView extends React.Component {
UIManager.RCTPSPDFKitView.Commands.saveCurrentDocument,
[]
)
} else if (Platform.OS === "ios"){
} else if (Platform.OS === "ios") {
NativeModules.PSPDFKitViewManager.saveCurrentDocument(findNodeHandle(this.refs.pdfView));
}
}

/**
* Gets all annotations of the given type from the page.
*
Expand All @@ -154,7 +154,7 @@ class PSPDFKitView extends React.Component {
);

return promise
} else if (Platform.OS === "ios"){
} else if (Platform.OS === "ios") {
return NativeModules.PSPDFKitViewManager.getAnnotations(pageIndex, type, findNodeHandle(this.refs.pdfView));
}
}
Expand All @@ -171,8 +171,8 @@ class PSPDFKitView extends React.Component {
UIManager.RCTPSPDFKitView.Commands.addAnnotation,
[annotation]
);
} else if (Platform.OS === "ios"){
NativeModules.PSPDFKitViewManager.addAnnotation(annotation, findNodeHandle(this.refs.pdfView));
} else if (Platform.OS === "ios") {
NativeModules.PSPDFKitViewManager.addAnnotation(annotation, findNodeHandle(this.refs.pdfView));
}
}

Expand All @@ -198,7 +198,7 @@ class PSPDFKitView extends React.Component {
);

return promise
} else if (Platform.OS === "ios"){
} else if (Platform.OS === "ios") {
return NativeModules.PSPDFKitViewManager.getAllUnsavedAnnotations(findNodeHandle(this.refs.pdfView));
}
}
Expand All @@ -215,8 +215,56 @@ class PSPDFKitView extends React.Component {
UIManager.RCTPSPDFKitView.Commands.addAnnotations,
[annotations]
);
} else if (Platform.OS === "ios"){
NativeModules.PSPDFKitViewManager.addAnnotations(annotations, findNodeHandle(this.refs.pdfView));
} else if (Platform.OS === "ios") {
NativeModules.PSPDFKitViewManager.addAnnotations(annotations, findNodeHandle(this.refs.pdfView));
}
}

/**
* Gets the value of the form element of the fully qualified name.
*
* @param fullyQualifiedName The fully qualified name of the form element.
*
* Returns a promise resolving a dictionary with the following structure:
* {'formElement' : value} or {'error' : 'Failed to get the form field value.'}
*
* @platform android
*/
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.refs.pdfView),
UIManager.RCTPSPDFKitView.Commands.getFormFieldValue,
[requestId, fullyQualifiedName]
);

return promise;
}
}

/**
* Set the value of the form element of the fully qualified name.
*
* @param value The string value 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'.
* @param fullyQualifiedName The fully qualified name of the form element.
*
* @platform android
*/
setFormFieldValue = function (value, fullyQualifiedName) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order of parameters: why is the value parameter specified before target field fqn param? Is this a JS convention?

if (Platform.OS === "android") {
UIManager.dispatchViewManagerCommand(
findNodeHandle(this.refs.pdfView),
UIManager.RCTPSPDFKitView.Commands.setFormFieldValue,
[fullyQualifiedName, value]
);
}
}
}
Expand Down
Loading