From 083d5f0549533d8e6080491bdc76a75278f65aaa Mon Sep 17 00:00:00 2001 From: irgendeinich Date: Wed, 18 Jul 2018 13:20:19 +0200 Subject: [PATCH 1/7] Add support for onDocumentSaved callback on Android --- .../pspdfkit/react/ReactPdfViewManager.java | 4 +- .../events/PdfViewDocumentSavedEvent.java | 31 +++++++ .../main/java/com/pspdfkit/views/PdfView.java | 6 ++ .../views/PdfViewDocumentListener.java | 82 +++++++++++++++++++ index.js | 4 +- 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java create mode 100644 android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java diff --git a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java index 8c759756..08ba675a 100644 --- a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java +++ b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java @@ -11,6 +11,7 @@ import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; +import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; import com.pspdfkit.react.events.PdfViewStateChangedEvent; import com.pspdfkit.views.PdfView; @@ -85,7 +86,8 @@ public void setPageIndex(PdfView view, int pageIndex) { @Nullable @Override public Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged")); + return MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"), + PdfViewDocumentSavedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaved")); } @Override diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java new file mode 100644 index 00000000..1c5d2555 --- /dev/null +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java @@ -0,0 +1,31 @@ +package com.pspdfkit.react.events; + +import android.support.annotation.IdRes; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.uimanager.events.Event; +import com.facebook.react.uimanager.events.RCTEventEmitter; + +/** + * Event sent by the {@link com.pspdfkit.views.PdfView} when the document was saved. + */ +public class PdfViewDocumentSavedEvent extends Event { + + public static final String EVENT_NAME = "pdfViewDocumentSaved"; + + public PdfViewDocumentSavedEvent(@IdRes int viewId) { + super(viewId); + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void dispatch(RCTEventEmitter rctEventEmitter) { + WritableMap eventData = Arguments.createMap(); + rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); + } +} diff --git a/android/src/main/java/com/pspdfkit/views/PdfView.java b/android/src/main/java/com/pspdfkit/views/PdfView.java index 3269b5bb..92c3f2d5 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfView.java +++ b/android/src/main/java/com/pspdfkit/views/PdfView.java @@ -17,6 +17,7 @@ import com.pspdfkit.configuration.activity.PdfActivityConfiguration; import com.pspdfkit.configuration.activity.ThumbnailBarMode; import com.pspdfkit.document.PdfDocument; +import com.pspdfkit.listeners.DocumentListener; import com.pspdfkit.listeners.SimpleDocumentListener; import com.pspdfkit.react.R; import com.pspdfkit.react.events.PdfViewStateChangedEvent; @@ -51,6 +52,7 @@ public class PdfView extends FrameLayout { private FrameLayout container; private PdfViewModeController pdfViewModeController; + private PdfViewDocumentListener pdfViewDocumentListener; private PdfThumbnailBar pdfThumbnailBar; @@ -114,6 +116,9 @@ public void doFrame(long frameTimeNanos) { public void inject(FragmentManager fragmentManager, EventDispatcher eventDispatcher) { this.fragmentManager = fragmentManager; this.eventDispatcher = eventDispatcher; + + pdfViewDocumentListener = new PdfViewDocumentListener(this, + eventDispatcher); } public void setFragmentTag(String fragmentTag) { @@ -206,6 +211,7 @@ public void onPageChanged(@NonNull PdfDocument document, int pageIndex) { pdfFragment.addOnAnnotationEditingModeChangeListener(pdfViewModeController); pdfFragment.addOnFormElementEditingModeChangeListener(pdfViewModeController); pdfFragment.addOnTextSelectionModeChangeListener(pdfViewModeController); + pdfFragment.addDocumentListener(pdfViewDocumentListener); setupThumbnailBar(pdfFragment); diff --git a/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java new file mode 100644 index 00000000..216fc13c --- /dev/null +++ b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java @@ -0,0 +1,82 @@ +package com.pspdfkit.views; + +import android.graphics.PointF; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.MotionEvent; + +import com.facebook.react.uimanager.events.EventDispatcher; +import com.pspdfkit.annotations.Annotation; +import com.pspdfkit.document.DocumentSaveOptions; +import com.pspdfkit.document.PdfDocument; +import com.pspdfkit.listeners.DocumentListener; +import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; + +class PdfViewDocumentListener implements DocumentListener { + + @NonNull + private final PdfView parent; + + @NonNull + private final EventDispatcher eventDispatcher; + + PdfViewDocumentListener(@NonNull PdfView parent, @NonNull EventDispatcher eventDispatcher) { + this.parent = parent; + this.eventDispatcher = eventDispatcher; + } + + @Override + public void onDocumentLoaded(@NonNull PdfDocument pdfDocument) { + + } + + @Override + public void onDocumentLoadFailed(@NonNull Throwable throwable) { + + } + + @Override + public boolean onDocumentSave(@NonNull PdfDocument pdfDocument, @NonNull DocumentSaveOptions documentSaveOptions) { + return true; + } + + @Override + public void onDocumentSaved(@NonNull PdfDocument pdfDocument) { + eventDispatcher.dispatchEvent(new PdfViewDocumentSavedEvent(parent.getId())); + } + + @Override + public void onDocumentSaveFailed(@NonNull PdfDocument pdfDocument, @NonNull Throwable throwable) { + + } + + @Override + public void onDocumentSaveCancelled(PdfDocument pdfDocument) { + + } + + @Override + public boolean onPageClick(@NonNull PdfDocument pdfDocument, int i, @Nullable MotionEvent motionEvent, @Nullable PointF pointF, @Nullable Annotation annotation) { + return false; + } + + @Override + public boolean onDocumentClick() { + return false; + } + + @Override + public void onPageChanged(@NonNull PdfDocument pdfDocument, int i) { + + } + + @Override + public void onDocumentZoomed(@NonNull PdfDocument pdfDocument, int i, float v) { + + } + + @Override + public void onPageUpdated(@NonNull PdfDocument pdfDocument, int i) { + + } +} \ No newline at end of file diff --git a/index.js b/index.js index f31a68db..a9706f0b 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -// Copyright © 2018 PSPDFKit GmbH. All rights reserved. +// Copyright � 2018 PSPDFKit GmbH. 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. @@ -130,8 +130,6 @@ PSPDFKitView.propTypes = { onCloseButtonPressed: PropTypes.func, /** * Callback that is called when the document is saved. - * - * @platform ios */ onDocumentSaved: PropTypes.func, /** From d500b2bb64705fc7a847bac5e0d4019c55fb4641 Mon Sep 17 00:00:00 2001 From: irgendeinich Date: Wed, 18 Jul 2018 15:13:20 +0200 Subject: [PATCH 2/7] Add support for disableDefaultActionForTappedAnnotations and onAnnotationTapped to Android --- .../pspdfkit/react/ReactPdfViewManager.java | 9 +- .../events/PdfViewAnnotationTappedEvent.java | 94 +++++++++++++++++++ .../main/java/com/pspdfkit/views/PdfView.java | 6 +- .../views/PdfViewDocumentListener.java | 22 ++++- index.js | 5 +- 5 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java diff --git a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java index 08ba675a..39cf06eb 100644 --- a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java +++ b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java @@ -11,6 +11,7 @@ import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; +import com.pspdfkit.react.events.PdfViewAnnotationTappedEvent; import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; import com.pspdfkit.react.events.PdfViewStateChangedEvent; import com.pspdfkit.views.PdfView; @@ -83,11 +84,17 @@ public void setPageIndex(PdfView view, int pageIndex) { view.setPageIndex(pageIndex); } + @ReactProp(name = "disableDefaultActionForTappedAnnotations") + public void setDisableDefaultActionForTappedAnnotations(PdfView view, boolean disableDefaultActionForTappedAnnotations) { + view.setDisableDefaultActionForTappedAnnotations(disableDefaultActionForTappedAnnotations); + } + @Nullable @Override public Map getExportedCustomDirectEventTypeConstants() { return MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"), - PdfViewDocumentSavedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaved")); + PdfViewDocumentSavedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaved"), + PdfViewAnnotationTappedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationTapped")); } @Override diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java new file mode 100644 index 00000000..2bace211 --- /dev/null +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java @@ -0,0 +1,94 @@ +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; +import com.facebook.react.uimanager.events.Event; +import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.pspdfkit.annotations.Annotation; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Event sent by the {@link com.pspdfkit.views.PdfView} when an annotation was selected. + */ +public class PdfViewAnnotationTappedEvent extends Event { + + public static final String EVENT_NAME = "pdfViewAnnotationTapped"; + + @NonNull + private final Annotation annotation; + + public PdfViewAnnotationTappedEvent(@IdRes int viewId, @NonNull Annotation annotation) { + super(viewId); + this.annotation = annotation; + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void dispatch(RCTEventEmitter rctEventEmitter) { + try { + JSONObject instantJson = new JSONObject(annotation.toInstantJson()); + Map map = jsonToMap(instantJson); + WritableMap eventData = Arguments.makeNativeMap(map); + rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + private static Map jsonToMap(JSONObject json) throws JSONException { + Map retMap = new HashMap<>(); + + if (json != JSONObject.NULL) { + retMap = toMap(json); + } + return retMap; + } + + private static Map toMap(JSONObject object) throws JSONException { + Map map = new HashMap<>(); + + Iterator keysItr = object.keys(); + while (keysItr.hasNext()) { + String key = keysItr.next(); + Object value = object.get(key); + + if (value instanceof JSONArray) { + value = toList((JSONArray) value); + } else if (value instanceof JSONObject) { + value = toMap((JSONObject) value); + } + map.put(key, value); + } + return map; + } + + private static List toList(JSONArray array) throws JSONException { + List list = new ArrayList<>(); + for (int i = 0; i < array.length(); i++) { + Object value = array.get(i); + if (value instanceof JSONArray) { + value = toList((JSONArray) value); + } else if (value instanceof JSONObject) { + value = toMap((JSONObject) value); + } + list.add(value); + } + return list; + } +} \ No newline at end of file diff --git a/android/src/main/java/com/pspdfkit/views/PdfView.java b/android/src/main/java/com/pspdfkit/views/PdfView.java index 92c3f2d5..ae97ef34 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfView.java +++ b/android/src/main/java/com/pspdfkit/views/PdfView.java @@ -17,7 +17,6 @@ import com.pspdfkit.configuration.activity.PdfActivityConfiguration; import com.pspdfkit.configuration.activity.ThumbnailBarMode; import com.pspdfkit.document.PdfDocument; -import com.pspdfkit.listeners.DocumentListener; import com.pspdfkit.listeners.SimpleDocumentListener; import com.pspdfkit.react.R; import com.pspdfkit.react.events.PdfViewStateChangedEvent; @@ -157,6 +156,10 @@ public void setPageIndex(int pageIndex) { setupFragment(); } + public void setDisableDefaultActionForTappedAnnotations(boolean disableDefaultActionForTappedAnnotations) { + pdfViewDocumentListener.setDisableDefaultActionForTappedAnnotations(disableDefaultActionForTappedAnnotations); + } + private void setupFragment() { if (fragmentTag != null && configuration != null && document != null) { PdfFragment pdfFragment = (PdfFragment) fragmentManager.findFragmentByTag(fragmentTag); @@ -212,6 +215,7 @@ public void onPageChanged(@NonNull PdfDocument document, int pageIndex) { pdfFragment.addOnFormElementEditingModeChangeListener(pdfViewModeController); pdfFragment.addOnTextSelectionModeChangeListener(pdfViewModeController); pdfFragment.addDocumentListener(pdfViewDocumentListener); + pdfFragment.addOnAnnotationSelectedListener(pdfViewDocumentListener); setupThumbnailBar(pdfFragment); diff --git a/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java index 216fc13c..3f9ef1b3 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java +++ b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java @@ -10,9 +10,12 @@ import com.pspdfkit.document.DocumentSaveOptions; import com.pspdfkit.document.PdfDocument; import com.pspdfkit.listeners.DocumentListener; +import com.pspdfkit.react.events.PdfViewAnnotationTappedEvent; import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; +import com.pspdfkit.ui.special_mode.controller.AnnotationSelectionController; +import com.pspdfkit.ui.special_mode.manager.AnnotationManager; -class PdfViewDocumentListener implements DocumentListener { +class PdfViewDocumentListener implements DocumentListener, AnnotationManager.OnAnnotationSelectedListener { @NonNull private final PdfView parent; @@ -20,11 +23,18 @@ class PdfViewDocumentListener implements DocumentListener { @NonNull private final EventDispatcher eventDispatcher; + private boolean disableDefaultActionForTappedAnnotations = false; + PdfViewDocumentListener(@NonNull PdfView parent, @NonNull EventDispatcher eventDispatcher) { this.parent = parent; this.eventDispatcher = eventDispatcher; } + + public void setDisableDefaultActionForTappedAnnotations(boolean disableDefaultActionForTappedAnnotations) { + this.disableDefaultActionForTappedAnnotations = disableDefaultActionForTappedAnnotations; + } + @Override public void onDocumentLoaded(@NonNull PdfDocument pdfDocument) { @@ -79,4 +89,14 @@ public void onDocumentZoomed(@NonNull PdfDocument pdfDocument, int i, float v) { public void onPageUpdated(@NonNull PdfDocument pdfDocument, int i) { } + + @Override + public boolean onPrepareAnnotationSelection(@NonNull AnnotationSelectionController annotationSelectionController, @NonNull Annotation annotation, boolean annotationCreated) { + eventDispatcher.dispatchEvent(new PdfViewAnnotationTappedEvent(parent.getId(), annotation)); + return !disableDefaultActionForTappedAnnotations; + } + + @Override + public void onAnnotationSelected(@NonNull Annotation annotation, boolean annotationCreated) { + } } \ No newline at end of file diff --git a/index.js b/index.js index a9706f0b..1d34f087 100644 --- a/index.js +++ b/index.js @@ -116,8 +116,6 @@ PSPDFKitView.propTypes = { showCloseButton: PropTypes.bool, /** * Controls wheter or not the default action for tapped annotations is processed. Defaults to processing the action (false). - * - * @platform ios */ disableDefaultActionForTappedAnnotations: PropTypes.bool, /** @@ -134,8 +132,7 @@ PSPDFKitView.propTypes = { onDocumentSaved: PropTypes.func, /** * Callback that is called when the user taps on an annotation. - * - * @platform ios + * Returns the annotation data as instant json. */ onAnnotationTapped: PropTypes.func, /** From 990004bbf846453e39a0f9ca8c9ef8fb8fb2076f Mon Sep 17 00:00:00 2001 From: irgendeinich Date: Wed, 18 Jul 2018 16:43:52 +0200 Subject: [PATCH 3/7] Adds support for onAnnotationChanged on Android --- .../pspdfkit/react/ReactPdfViewManager.java | 4 +- .../events/PdfViewAnnotationChangedEvent.java | 70 +++++++++++++++++++ .../events/PdfViewAnnotationTappedEvent.java | 49 +------------ .../pspdfkit/react/helper/JsonUtilities.java | 49 +++++++++++++ .../main/java/com/pspdfkit/views/PdfView.java | 1 + .../views/PdfViewDocumentListener.java | 19 ++++- index.js | 18 ++++- 7 files changed, 160 insertions(+), 50 deletions(-) create mode 100644 android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java create mode 100644 android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java diff --git a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java index 39cf06eb..ba214faa 100644 --- a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java +++ b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java @@ -11,6 +11,7 @@ import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; +import com.pspdfkit.react.events.PdfViewAnnotationChangedEvent; import com.pspdfkit.react.events.PdfViewAnnotationTappedEvent; import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; import com.pspdfkit.react.events.PdfViewStateChangedEvent; @@ -94,7 +95,8 @@ public void setDisableDefaultActionForTappedAnnotations(PdfView view, boolean di public Map getExportedCustomDirectEventTypeConstants() { return MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"), PdfViewDocumentSavedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaved"), - PdfViewAnnotationTappedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationTapped")); + PdfViewAnnotationTappedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationTapped"), + PdfViewAnnotationChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationChanged")); } @Override diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java new file mode 100644 index 00000000..ee454333 --- /dev/null +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java @@ -0,0 +1,70 @@ +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; +import com.facebook.react.uimanager.events.Event; +import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.pspdfkit.annotations.Annotation; +import com.pspdfkit.react.helper.JsonUtilities; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Map; + +/** + * Event sent by the {@link com.pspdfkit.views.PdfView} when an annotation was selected. + */ +public class PdfViewAnnotationChangedEvent extends Event { + + public static final String EVENT_NAME = "pdfViewAnnotationChanged"; + public static final String EVENT_TYPE_CHANGED = "changed"; + public static final String EVENT_TYPE_ADDED = "added"; + public static final String EVENT_TYPE_REMOVED = "removed"; + + @NonNull + private final String eventType; + + @NonNull + private final Annotation annotation; + + public PdfViewAnnotationChangedEvent(@IdRes int viewId, @NonNull String eventType, @NonNull Annotation annotation) { + super(viewId); + this.eventType = eventType; + this.annotation = annotation; + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void dispatch(RCTEventEmitter rctEventEmitter) { + try { + Map map = new HashMap<>(); + map.put("change", eventType); + + if (EVENT_TYPE_REMOVED.equalsIgnoreCase(eventType)) { + // For removed annotation we can't get the instant json so manually create something. + Map annotationMap = new HashMap<>(); + annotationMap.put("name", annotation.getName()); + annotationMap.put("creatorName", annotation.getCreator()); + map.put("annotation", annotationMap); + } else { + JSONObject instantJson = new JSONObject(annotation.toInstantJson()); + Map instantJsonMap = JsonUtilities.jsonObjectToMap(instantJson); + map.put("annotation", instantJsonMap); + } + + WritableMap eventData = Arguments.makeNativeMap(map); + rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); + } catch (JSONException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java index 2bace211..a7ee10b9 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java @@ -8,15 +8,11 @@ import com.facebook.react.uimanager.events.Event; import com.facebook.react.uimanager.events.RCTEventEmitter; import com.pspdfkit.annotations.Annotation; +import com.pspdfkit.react.helper.JsonUtilities; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; /** @@ -43,52 +39,11 @@ public String getEventName() { public void dispatch(RCTEventEmitter rctEventEmitter) { try { JSONObject instantJson = new JSONObject(annotation.toInstantJson()); - Map map = jsonToMap(instantJson); + Map map = JsonUtilities.jsonObjectToMap(instantJson); WritableMap eventData = Arguments.makeNativeMap(map); rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); } catch (JSONException e) { e.printStackTrace(); } } - - private static Map jsonToMap(JSONObject json) throws JSONException { - Map retMap = new HashMap<>(); - - if (json != JSONObject.NULL) { - retMap = toMap(json); - } - return retMap; - } - - private static Map toMap(JSONObject object) throws JSONException { - Map map = new HashMap<>(); - - Iterator keysItr = object.keys(); - while (keysItr.hasNext()) { - String key = keysItr.next(); - Object value = object.get(key); - - if (value instanceof JSONArray) { - value = toList((JSONArray) value); - } else if (value instanceof JSONObject) { - value = toMap((JSONObject) value); - } - map.put(key, value); - } - return map; - } - - private static List toList(JSONArray array) throws JSONException { - List list = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - Object value = array.get(i); - if (value instanceof JSONArray) { - value = toList((JSONArray) value); - } else if (value instanceof JSONObject) { - value = toMap((JSONObject) value); - } - list.add(value); - } - return list; - } } \ No newline at end of file diff --git a/android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java b/android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java new file mode 100644 index 00000000..488a6f5d --- /dev/null +++ b/android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java @@ -0,0 +1,49 @@ +package com.pspdfkit.react.helper; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class JsonUtilities { + + /** + * Converts the given {@link JSONObject} to a {@link Map}. + */ + public static Map jsonObjectToMap(JSONObject object) throws JSONException { + Map map = new HashMap<>(); + + Iterator keysItr = object.keys(); + while (keysItr.hasNext()) { + String key = keysItr.next(); + Object value = object.get(key); + + if (value instanceof JSONArray) { + value = toList((JSONArray) value); + } else if (value instanceof JSONObject) { + value = jsonObjectToMap((JSONObject) value); + } + map.put(key, value); + } + return map; + } + + private static List toList(JSONArray array) throws JSONException { + List list = new ArrayList<>(); + for (int i = 0; i < array.length(); i++) { + Object value = array.get(i); + if (value instanceof JSONArray) { + value = toList((JSONArray) value); + } else if (value instanceof JSONObject) { + value = jsonObjectToMap((JSONObject) value); + } + list.add(value); + } + return list; + } +} diff --git a/android/src/main/java/com/pspdfkit/views/PdfView.java b/android/src/main/java/com/pspdfkit/views/PdfView.java index ae97ef34..39429871 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfView.java +++ b/android/src/main/java/com/pspdfkit/views/PdfView.java @@ -216,6 +216,7 @@ public void onPageChanged(@NonNull PdfDocument document, int pageIndex) { pdfFragment.addOnTextSelectionModeChangeListener(pdfViewModeController); pdfFragment.addDocumentListener(pdfViewDocumentListener); pdfFragment.addOnAnnotationSelectedListener(pdfViewDocumentListener); + pdfFragment.addOnAnnotationUpdatedListener(pdfViewDocumentListener); setupThumbnailBar(pdfFragment); diff --git a/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java index 3f9ef1b3..60bba371 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java +++ b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java @@ -7,15 +7,17 @@ import com.facebook.react.uimanager.events.EventDispatcher; import com.pspdfkit.annotations.Annotation; +import com.pspdfkit.annotations.AnnotationProvider; import com.pspdfkit.document.DocumentSaveOptions; import com.pspdfkit.document.PdfDocument; import com.pspdfkit.listeners.DocumentListener; +import com.pspdfkit.react.events.PdfViewAnnotationChangedEvent; import com.pspdfkit.react.events.PdfViewAnnotationTappedEvent; import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; import com.pspdfkit.ui.special_mode.controller.AnnotationSelectionController; import com.pspdfkit.ui.special_mode.manager.AnnotationManager; -class PdfViewDocumentListener implements DocumentListener, AnnotationManager.OnAnnotationSelectedListener { +class PdfViewDocumentListener implements DocumentListener, AnnotationManager.OnAnnotationSelectedListener, AnnotationProvider.OnAnnotationUpdatedListener { @NonNull private final PdfView parent; @@ -99,4 +101,19 @@ public boolean onPrepareAnnotationSelection(@NonNull AnnotationSelectionControll @Override public void onAnnotationSelected(@NonNull Annotation annotation, boolean annotationCreated) { } + + @Override + public void onAnnotationCreated(@NonNull Annotation annotation) { + eventDispatcher.dispatchEvent(new PdfViewAnnotationChangedEvent(parent.getId(), PdfViewAnnotationChangedEvent.EVENT_TYPE_ADDED, annotation)); + } + + @Override + public void onAnnotationUpdated(@NonNull Annotation annotation) { + eventDispatcher.dispatchEvent(new PdfViewAnnotationChangedEvent(parent.getId(), PdfViewAnnotationChangedEvent.EVENT_TYPE_CHANGED, annotation)); + } + + @Override + public void onAnnotationRemoved(@NonNull Annotation annotation) { + eventDispatcher.dispatchEvent(new PdfViewAnnotationChangedEvent(parent.getId(), PdfViewAnnotationChangedEvent.EVENT_TYPE_REMOVED, annotation)); + } } \ No newline at end of file diff --git a/index.js b/index.js index 1d34f087..6e556de1 100644 --- a/index.js +++ b/index.js @@ -31,6 +31,7 @@ class PSPDFKitView extends React.Component { onStateChanged={this._onStateChanged} onDocumentSaved={this._onDocumentSaved} onAnnotationTapped={this._onAnnotationTapped} + onAnnotationChanged={this._onAnnotationChanged} /> ); } else { @@ -56,6 +57,12 @@ class PSPDFKitView extends React.Component { } }; + _onAnnotationChanged = event => { + if (this.props.onAnnotationChanged) { + this.props.onAnnotationChanged(event.nativeEvent) + } + } + /** * Enters the annotation creation mode, showing the annotation creation toolbar. * @@ -134,7 +141,16 @@ PSPDFKitView.propTypes = { * Callback that is called when the user taps on an annotation. * Returns the annotation data as instant json. */ - onAnnotationTapped: PropTypes.func, + onAnnotationTapped: PropTypes.func, + /** + * Callback that is called when an annotation is added, changed, or removed. + * Returns an object with the following structure: + * { + * change: "changed"|"added"|"removed", + * annotation: instantJson + * } + */ + onAnnotationChanged: PropTypes.func, /** * Callback that is called when the state of the PSPDFKitView changes. * Returns an object with the following structure: From a448c50ab29816679353752e2cdfa4339821eca7 Mon Sep 17 00:00:00 2001 From: irgendeinich Date: Wed, 18 Jul 2018 17:11:29 +0200 Subject: [PATCH 4/7] Add saveCurrentDocument to Android --- .../com/pspdfkit/react/ReactPdfViewManager.java | 8 +++++++- .../src/main/java/com/pspdfkit/views/PdfView.java | 6 ++++++ index.js | 13 ++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java index ba214faa..823beb48 100644 --- a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java +++ b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java @@ -28,6 +28,7 @@ public class ReactPdfViewManager extends ViewGroupManager { public static final int COMMAND_ENTER_ANNOTATION_CREATION_MODE = 1; public static final int COMMAND_EXIT_CURRENTLY_ACTIVE_MODE = 2; + public static final int COMMAND_SAVE_CURRENT_DOCUMENT = 3; @Override public String getName() { @@ -61,7 +62,9 @@ public Map getCommandsMap() { "enterAnnotationCreationMode", COMMAND_ENTER_ANNOTATION_CREATION_MODE, "exitCurrentlyActiveMode", - COMMAND_EXIT_CURRENTLY_ACTIVE_MODE); + COMMAND_EXIT_CURRENTLY_ACTIVE_MODE, + "saveCurrentDocument", + COMMAND_SAVE_CURRENT_DOCUMENT); } @ReactProp(name = "fragmentTag") @@ -108,6 +111,9 @@ public void receiveCommand(PdfView root, int commandId, @Nullable ReadableArray case COMMAND_EXIT_CURRENTLY_ACTIVE_MODE: root.exitCurrentlyActiveMode(); break; + case COMMAND_SAVE_CURRENT_DOCUMENT: + root.saveCurrentDocument(); + break; } } diff --git a/android/src/main/java/com/pspdfkit/views/PdfView.java b/android/src/main/java/com/pspdfkit/views/PdfView.java index 39429871..6f815051 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfView.java +++ b/android/src/main/java/com/pspdfkit/views/PdfView.java @@ -309,4 +309,10 @@ public void exitCurrentlyActiveMode() { fragment.exitCurrentlyActiveMode(); } } + + public void saveCurrentDocument() { + if (fragment != null) { + fragment.save(); + } + } } diff --git a/index.js b/index.js index 6e556de1..5bf31679 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -// Copyright � 2018 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018 PSPDFKit GmbH. 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. @@ -88,6 +88,17 @@ class PSPDFKitView extends React.Component { [] ); }; + + /** + * Saves the currently opened document. + */ + saveCurrentDocument = function () { + UIManager.dispatchViewManagerCommand( + findNodeHandle(this.refs.pdfView), + UIManager.RCTPSPDFKitView.Commands.saveCurrentDocument, + [] + ) + } } PSPDFKitView.propTypes = { From f9149f8aebc09f8ae59186d5b5795d6bb7b6a0e4 Mon Sep 17 00:00:00 2001 From: irgendeinich Date: Thu, 19 Jul 2018 10:56:38 +0200 Subject: [PATCH 5/7] onAnnotationChanged -> onAnnotationsChanged --- .../com/pspdfkit/react/ReactPdfViewManager.java | 2 +- .../react/events/PdfViewAnnotationChangedEvent.java | 13 +++++++++---- index.js | 12 ++++++------ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java index 823beb48..51c1b2d7 100644 --- a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java +++ b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java @@ -99,7 +99,7 @@ public Map getExportedCustomDirectEventTypeConstants() { return MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"), PdfViewDocumentSavedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaved"), PdfViewAnnotationTappedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationTapped"), - PdfViewAnnotationChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationChanged")); + PdfViewAnnotationChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationsChanged")); } @Override diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java index ee454333..21c98140 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java @@ -13,7 +13,9 @@ import org.json.JSONException; import org.json.JSONObject; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -49,18 +51,21 @@ public void dispatch(RCTEventEmitter rctEventEmitter) { Map map = new HashMap<>(); map.put("change", eventType); + Map annotationMap; if (EVENT_TYPE_REMOVED.equalsIgnoreCase(eventType)) { // For removed annotation we can't get the instant json so manually create something. - Map annotationMap = new HashMap<>(); + annotationMap = new HashMap<>(); annotationMap.put("name", annotation.getName()); annotationMap.put("creatorName", annotation.getCreator()); - map.put("annotation", annotationMap); } else { JSONObject instantJson = new JSONObject(annotation.toInstantJson()); - Map instantJsonMap = JsonUtilities.jsonObjectToMap(instantJson); - map.put("annotation", instantJsonMap); + annotationMap = JsonUtilities.jsonObjectToMap(instantJson); } + List> annotations = new ArrayList<>(); + annotations.add(annotationMap); + map.put("annotations", annotations); + WritableMap eventData = Arguments.makeNativeMap(map); rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); } catch (JSONException e) { diff --git a/index.js b/index.js index 5bf31679..c0203d77 100644 --- a/index.js +++ b/index.js @@ -31,7 +31,7 @@ class PSPDFKitView extends React.Component { onStateChanged={this._onStateChanged} onDocumentSaved={this._onDocumentSaved} onAnnotationTapped={this._onAnnotationTapped} - onAnnotationChanged={this._onAnnotationChanged} + onAnnotationsChanged={this._onAnnotationsChanged} /> ); } else { @@ -57,9 +57,9 @@ class PSPDFKitView extends React.Component { } }; - _onAnnotationChanged = event => { - if (this.props.onAnnotationChanged) { - this.props.onAnnotationChanged(event.nativeEvent) + _onAnnotationsChanged = event => { + if (this.props.onAnnotationsChanged) { + this.props.onAnnotationsChanged(event.nativeEvent) } } @@ -158,10 +158,10 @@ PSPDFKitView.propTypes = { * Returns an object with the following structure: * { * change: "changed"|"added"|"removed", - * annotation: instantJson + * annotations: [instantJson] * } */ - onAnnotationChanged: PropTypes.func, + onAnnotationsChanged: PropTypes.func, /** * Callback that is called when the state of the PSPDFKitView changes. * Returns an object with the following structure: From 7c9b6df84dc9120b92d602a0e90a19a3e4886862 Mon Sep 17 00:00:00 2001 From: irgendeinich Date: Thu, 19 Jul 2018 11:48:49 +0200 Subject: [PATCH 6/7] Expand example with page navigation buttons --- .../main/java/com/pspdfkit/views/PdfView.java | 6 +- samples/Catalog/Catalog.android.js | 60 ++++++++++++------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/android/src/main/java/com/pspdfkit/views/PdfView.java b/android/src/main/java/com/pspdfkit/views/PdfView.java index 6f815051..08295c9d 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfView.java +++ b/android/src/main/java/com/pspdfkit/views/PdfView.java @@ -167,7 +167,7 @@ private void setupFragment() { pdfFragment = PdfFragment.newInstance(document, this.configuration.getConfiguration()); prepareFragment(pdfFragment); } else { - ViewGroup parent = (ViewGroup) pdfFragment.getView().getParent(); + View fragmentView = pdfFragment.getView(); if (pdfFragment.getDocument() != null && !pdfFragment.getDocument().getUid().equals(document.getUid())) { fragmentManager.beginTransaction() .remove(pdfFragment) @@ -176,7 +176,7 @@ private void setupFragment() { // The document changed create a new PdfFragment. pdfFragment = PdfFragment.newInstance(document, this.configuration.getConfiguration()); prepareFragment(pdfFragment); - } else if (parent != this) { + } else if (fragmentView != null && fragmentView.getParent() != this) { // We only need to detach the fragment if the parent view changed. pdfViewModeController.resetToolbars(); fragmentManager.beginTransaction() @@ -223,7 +223,7 @@ public void onPageChanged(@NonNull PdfDocument document, int pageIndex) { fragmentManager.beginTransaction() .add(pdfFragment, fragmentTag) .commitNow(); - View fragmentView = pdfFragment.onCreateView(LayoutInflater.from(getContext()), this, null); + View fragmentView = pdfFragment.getView(); addView(fragmentView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } diff --git a/samples/Catalog/Catalog.android.js b/samples/Catalog/Catalog.android.js index 8d5ff2b9..120abbe2 100644 --- a/samples/Catalog/Catalog.android.js +++ b/samples/Catalog/Catalog.android.js @@ -67,8 +67,8 @@ var examples = [ name: "Open local document", description: "Open document from external storage directory.", action: () => { - requestExternalStoragePermission(function() { - extractFromAssetsIfMissing("Annual Report.pdf", function() { + requestExternalStoragePermission(function () { + extractFromAssetsIfMissing("Annual Report.pdf", function () { PSPDFKit.present(DOCUMENT, {}); }); }); @@ -78,8 +78,8 @@ var examples = [ name: "Open local image document", description: "Open image image document from external storage directory.", action: () => { - requestExternalStoragePermission(function() { - extractFromAssetsIfMissing("android.png", function() { + requestExternalStoragePermission(function () { + extractFromAssetsIfMissing("android.png", function () { PSPDFKit.presentImage(IMAGE_DOCUMENT, CONFIGURATION_IMAGE_DOCUMENT); }); }); @@ -90,7 +90,7 @@ var examples = [ description: "You can configure the builder with dictionary representation of the PSPDFConfiguration object.", action: () => { - requestExternalStoragePermission(function() { + requestExternalStoragePermission(function () { PSPDFKit.present(DOCUMENT, CONFIGURATION); }); } @@ -131,28 +131,28 @@ function extractFromAssetsIfMissing(assetFile, callback) { console.log(assetFile + " does not exist, extracting it from assets folder to the external storage directory."); RNFS.existsAssets(assetFile).then((exist) => { // Check if the file is present in the assets folder. - if(exist) { + if (exist) { // File exists so it can be extracted to the external storage directory. RNFS.copyFileAssets(assetFile, "/sdcard/" + assetFile).then(() => { // File copied successfully from assets folder to external storage directory. callback(); }) - .catch((error) => { - console.log(error); - }); + .catch((error) => { + console.log(error); + }); } else { // File does not exist, it should never happen. throw new Error(assetFile + " couldn't be extracted as it was not found in the project assets folder."); } }) - .catch((error) => { - console.log(error); - }); + .catch((error) => { + console.log(error); + }); } }) - .catch((error) => { - console.log(error); - }); + .catch((error) => { + console.log(error); + }); } async function requestExternalStoragePermission(callback) { @@ -286,7 +286,7 @@ class PdfViewScreen extends Component<{}> { backgroundColor: processColor("lightgrey"), showThumbnailBar: "scrollable" }} - pageIndex={4} + pageIndex={this.state.currentPageIndex} fragmentTag="PDF1" onStateChanged={event => { this.setState({ @@ -298,12 +298,28 @@ class PdfViewScreen extends Component<{}> { }} style={{ flex: 1, color: pspdfkitColor }} /> - - {"Page " + - (this.state.currentPageIndex + 1) + - " of " + - this.state.pageCount} - + + + {"Page " + + (this.state.currentPageIndex + 1) + + " of " + + this.state.pageCount} + + +