diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index bb3417b4..54c664a3 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -3439,6 +3439,34 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +## zlib (http://www.zlib.net/) + +zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + -------------------------------------------------------------------------------- ## Pdfium (https://pdfium.googlesource.com/) @@ -4060,31 +4088,3 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------------- -## zlib (http://www.zlib.net/) - -zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.11, January 15th, 2017 - - Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c583149..43c2487c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,26 @@ ## Newest Release +### 2.9.0 - 22 Mar 2024 + +- Adds new getConfiguration method to retrieve current PSPDFKitView configuration options. (J#HYB-192) +- Adds the option to open a password protected document through configuration. (J#HYB-213) +- Adds the ability to add custom toolbar buttons to the PSPDFKit toolbar. (J#HYB-198) +- Adds support for new `MeasurementValueConfiguration` configuration option, replacing deprecated `setMeasurementScale` and `setMeasurementPrecision` methods. (J#HYB-205) +- Updates `showPageLabels` property to also control page number overlay on Android. (J#HYB-223) +- Updates for PSPDFKit 2024.1.2 for Android. +- Updates for PSPDFKit 13.3.3 for iOS. +- Fixes issue of document URIs with file:/// scheme on iOS. (#43160) +- Fixes issue where `onDocumentLoaded` callback was not called on Android. (#43187) +- Fixes signatureSavingStrategy configuration option to save signature if enabled. (J#HYB-210) +- Fixes `spreadFitting` configuration option behaviour on iOS. (J#HYB-222) + +## Previous Releases + ### 2.8.1 - 27 Feb 2024 - Updates for PSPDFKit 13.3.1 for iOS. (#43565) - Removes `scrollViewInsetAdjustment`, `spreadFitting` and `allowedMenuActions` configuration options which are deprecated in PSPDFKit for iOS. (#43565) -## Previous Releases - ### 2.8.0 - 18 Dec 2023 - Adds TypeScript types support to PSPDFKit plugin. (#42380) diff --git a/LICENSE b/LICENSE index 55a90bb5..5ead30cd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -All items and source code Copyright © 2010-2023 PSPDFKit GmbH. +All items and source code Copyright © 2010-2024 PSPDFKit GmbH. PSPDFKit is a commercial product and requires a license to be used. diff --git a/README.md b/README.md index 6ca7b14a..1731c125 100644 --- a/README.md +++ b/README.md @@ -692,6 +692,6 @@ For Troubleshooting common issues you might encounter when setting up PSPDFKit f ## License This project can be used for evaluation or if you have a valid PSPDFKit license. -All items and source code Copyright © 2010-2023 PSPDFKit GmbH. +All items and source code Copyright © 2010-2024 PSPDFKit GmbH. See [LICENSE](./LICENSE) for details. diff --git a/android/build.gradle b/android/build.gradle index 75049012..dca47b98 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. @@ -15,7 +15,7 @@ * Contains gradle configuration constants */ ext { - PSPDFKIT_VERSION = '8.10.0' + PSPDFKIT_VERSION = '2024.1.2' } buildscript { @@ -70,6 +70,13 @@ dependencies { api("com.pspdfkit:pspdfkit:${PSPDFKIT_VERSION}") { exclude group: 'com.google.auto.value', module: 'auto-value' } + + implementation "androidx.compose.material:material:1.5.4" + implementation "androidx.constraintlayout:constraintlayout:2.1.4" + implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1" + implementation "androidx.compose.foundation:foundation:1.5.4" + implementation "androidx.compose.ui:ui:1.5.4" + implementation "com.facebook.react:react-native:+" implementation 'com.squareup.okhttp3:okhttp:4.9.2' implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 561a182b..2675fdaa 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -4,7 +4,7 @@ ~ ~ PSPDFKit ~ - ~ Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + ~ Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/AnnotationConfigurationAdaptor.kt b/android/src/main/java/com/pspdfkit/react/AnnotationConfigurationAdaptor.kt index a43d9206..cf2d26d0 100644 --- a/android/src/main/java/com/pspdfkit/react/AnnotationConfigurationAdaptor.kt +++ b/android/src/main/java/com/pspdfkit/react/AnnotationConfigurationAdaptor.kt @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. @@ -34,7 +34,6 @@ import com.pspdfkit.annotations.configuration.SoundAnnotationConfiguration import com.pspdfkit.annotations.configuration.StampAnnotationConfiguration import com.pspdfkit.annotations.stamps.StampPickerItem import com.pspdfkit.configuration.annotations.AnnotationAggregationStrategy -import com.pspdfkit.react.helper.MeasurementHelper import com.pspdfkit.ui.fonts.Font import com.pspdfkit.ui.inspector.views.BorderStylePreset import com.pspdfkit.ui.special_mode.controller.AnnotationTool @@ -70,8 +69,6 @@ const val MIN_TEXT_SIZE = "minimumTextSize" const val MAX_TEXT_SIZE = "maximumTextSize" const val DEFAULT_FONT = "defaultFont" const val AVAILABLE_FONTS = "availableFonts" -const val DEFAULT_SCALE = "defaultScale" -const val DEFAULT_PRECISION = "defaultPrecision" const val ANNOTATION_INK_PEN = "inkPen" const val ANNOTATION_INK_MAGIC = "inkMagic" @@ -306,16 +303,6 @@ class AnnotationConfigurationAdaptor { ) } - DEFAULT_SCALE -> configuration.getMap(key)?.let { scaleObject -> - val scale = MeasurementHelper.getScale(scaleObject) - builder.setDefaultScale(scale) - } - - DEFAULT_PRECISION -> configuration.getString(key)?.let { precisionString -> - val precision = MeasurementHelper.getPrecision(precisionString) - builder.setDefaultPrecision(precision) - } - MAX_ALPHA -> builder.setMaxAlpha(configuration.getDouble(key).toFloat()) MIN_ALPHA -> builder.setMinAlpha(configuration.getDouble(key).toFloat()) MAX_THICKNESS -> builder.setMaxThickness(configuration.getDouble(key).toFloat()) @@ -366,16 +353,6 @@ class AnnotationConfigurationAdaptor { builder.setAvailableColors(extractColors(colors.toArrayList().map { it as String })) } - DEFAULT_SCALE -> configuration.getMap(key)?.let { scaleObject -> - val scale = MeasurementHelper.getScale(scaleObject) - builder.setDefaultScale(scale) - } - - DEFAULT_PRECISION -> configuration.getString(key)?.let { precisionString -> - val precision = MeasurementHelper.getPrecision(precisionString) - builder.setDefaultPrecision(precision) - } - MAX_ALPHA -> builder.setMaxAlpha(configuration.getDouble(key).toFloat()) MIN_ALPHA -> builder.setMinAlpha(configuration.getDouble(key).toFloat()) MAX_THICKNESS -> builder.setMaxThickness(configuration.getDouble(key).toFloat()) @@ -429,16 +406,6 @@ class AnnotationConfigurationAdaptor { ) } - DEFAULT_SCALE -> configuration.getMap(key)?.let { scaleObject -> - val scale = MeasurementHelper.getScale(scaleObject) - builder.setDefaultScale(scale) - } - - DEFAULT_PRECISION -> configuration.getString(key)?.let { precisionString -> - val precision = MeasurementHelper.getPrecision(precisionString) - builder.setDefaultPrecision(precision) - } - DEFAULT_LINE_END -> configuration.getString(key)?.let { lineEndPair -> builder.setDefaultLineEnds(extractLineEndPair(lineEndPair)) } diff --git a/android/src/main/java/com/pspdfkit/react/ConfigurationAdapter.java b/android/src/main/java/com/pspdfkit/react/ConfigurationAdapter.java index b0e7cec5..96a4381a 100644 --- a/android/src/main/java/com/pspdfkit/react/ConfigurationAdapter.java +++ b/android/src/main/java/com/pspdfkit/react/ConfigurationAdapter.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. @@ -325,6 +325,61 @@ public ConfigurationAdapter(@NonNull final Context context, ReadableMap configur } } + public static List getStringValuesForConfigurationItems(final List items) { + List foundKeys = new ArrayList<>(); + for (AnnotationType item : items) { + foundKeys.add(item.toString()); + } + return foundKeys; + } + + public static String getStringValueForConfigurationItem(final Enum item) { + String resolvedValue = ""; + if (item instanceof PageScrollDirection) { + if (item == PageScrollDirection.HORIZONTAL) { resolvedValue = PAGE_SCROLL_DIRECTION_HORIZONTAL; } + else if (item == PageScrollDirection.VERTICAL) { resolvedValue = PAGE_SCROLL_DIRECTION_VERTICAL; } + } + + if (item instanceof PageScrollMode) { + if (item == PageScrollMode.PER_PAGE) { resolvedValue = PAGE_TRANSITION_PER_SPREAD; } + else if (item == PageScrollMode.CONTINUOUS) { resolvedValue = PAGE_TRANSITION_CONTINUOUS; } + } + + if (item instanceof PageLayoutMode) { + if (item == PageLayoutMode.AUTO) { resolvedValue = PAGE_MODE_AUTO; } + else if (item == PageLayoutMode.SINGLE) { resolvedValue = PAGE_MODE_SINGLE; } + else if (item == PageLayoutMode.DOUBLE) { resolvedValue = PAGE_MODE_DOUBLE; } + } + + if (item instanceof SignatureSavingStrategy) { + if (item == SignatureSavingStrategy.ALWAYS_SAVE) { resolvedValue = SIGNATURE_SAVING_STRATEGY_ALWAYS; } + else if (item == SignatureSavingStrategy.NEVER_SAVE) { resolvedValue = SIGNATURE_SAVING_STRATEGY_NEVER; } + else if (item == SignatureSavingStrategy.SAVE_IF_SELECTED) { resolvedValue = SIGNATURE_SAVING_STRATEGY_IF_SELECTED; } + } + + if (item instanceof PageFitMode) { + if (item == PageFitMode.FIT_TO_SCREEN) { resolvedValue = SPREAD_FITTING_FIT; } + else if (item == PageFitMode.FIT_TO_WIDTH) { resolvedValue = SPREAD_FITTING_FILL; } + } + + if (item instanceof UserInterfaceViewMode) { + if (item == UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_AUTOMATIC) { resolvedValue = USER_INTERFACE_VIEW_MODE_AUTOMATIC; } + else if (item == UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_AUTOMATIC_BORDER_PAGES) { resolvedValue = USER_INTERFACE_VIEW_MODE_AUTOMATIC_BORDER_PAGES; } + else if (item == UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_VISIBLE) { resolvedValue = USER_INTERFACE_VIEW_MODE_ALWAYS_VISIBLE; } + else if (item == UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_HIDDEN) { resolvedValue = USER_INTERFACE_VIEW_MODE_ALWAYS_HIDDEN; } + else if (item == UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_MANUAL) { resolvedValue = USER_INTERFACE_VIEW_MODE_ALWAYS_HIDDEN; } + } + + if (item instanceof ThumbnailBarMode) { + if (item == ThumbnailBarMode.THUMBNAIL_BAR_MODE_FLOATING) { resolvedValue = SHOW_THUMBNAIL_BAR_FLOATING; } + else if (item == ThumbnailBarMode.THUMBNAIL_BAR_MODE_NONE) { resolvedValue = SHOW_THUMBNAIL_BAR_NONE; } + else if (item == ThumbnailBarMode.THUMBNAIL_BAR_MODE_SCROLLABLE) { resolvedValue = SHOW_THUMBNAIL_BAR_SCROLLABLE; } + else if (item == ThumbnailBarMode.THUMBNAIL_BAR_MODE_PINNED) { resolvedValue = SHOW_THUMBNAIL_BAR_PINNED; } + } + + return resolvedValue; + } + private void configureShowPageNumberOverlay(final boolean showPageNumberOverlay) { if (showPageNumberOverlay) { configuration.showPageNumberOverlay(); @@ -499,8 +554,10 @@ private void configureShowAnnotationListAction(final boolean showAnnotationListA private void configureShowPageLabels(final boolean showPageLabels) { if (showPageLabels) { configuration.showPageLabels(); + configuration.showPageNumberOverlay(); } else { configuration.hidePageLabels(); + configuration.hidePageNumberOverlay(); } } diff --git a/android/src/main/java/com/pspdfkit/react/MainActivity.java b/android/src/main/java/com/pspdfkit/react/MainActivity.java index 03177571..f4debef1 100644 --- a/android/src/main/java/com/pspdfkit/react/MainActivity.java +++ b/android/src/main/java/com/pspdfkit/react/MainActivity.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/MainApplication.java b/android/src/main/java/com/pspdfkit/react/MainApplication.java index fab40d55..89ec8d1f 100644 --- a/android/src/main/java/com/pspdfkit/react/MainApplication.java +++ b/android/src/main/java/com/pspdfkit/react/MainApplication.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/PSPDFKitModule.java b/android/src/main/java/com/pspdfkit/react/PSPDFKitModule.java index 8c2b2d04..2c8b9d17 100644 --- a/android/src/main/java/com/pspdfkit/react/PSPDFKitModule.java +++ b/android/src/main/java/com/pspdfkit/react/PSPDFKitModule.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/PSPDFKitPackage.java b/android/src/main/java/com/pspdfkit/react/PSPDFKitPackage.java index d02532c6..df7e4148 100644 --- a/android/src/main/java/com/pspdfkit/react/PSPDFKitPackage.java +++ b/android/src/main/java/com/pspdfkit/react/PSPDFKitPackage.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/RNInstantPdfActivity.java b/android/src/main/java/com/pspdfkit/react/RNInstantPdfActivity.java index f95fda50..e5f3a02c 100644 --- a/android/src/main/java/com/pspdfkit/react/RNInstantPdfActivity.java +++ b/android/src/main/java/com/pspdfkit/react/RNInstantPdfActivity.java @@ -1,6 +1,6 @@ package com.pspdfkit.react; -/// Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. +/// Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/RNProcessor.java b/android/src/main/java/com/pspdfkit/react/RNProcessor.java index 7642ecea..01a93da3 100644 --- a/android/src/main/java/com/pspdfkit/react/RNProcessor.java +++ b/android/src/main/java/com/pspdfkit/react/RNProcessor.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java index 3d438487..5e4272f5 100644 --- a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java +++ b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. @@ -20,6 +20,8 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerModule; @@ -34,6 +36,8 @@ import com.pspdfkit.views.PdfView; import com.pspdfkit.configuration.activity.PdfActivityConfiguration; import org.json.JSONObject; + +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.HashMap; @@ -63,8 +67,10 @@ public class ReactPdfViewManager extends ViewGroupManager { public static final int COMMAND_REMOVE_FRAGMENT = 12; public static final int COMMAND_SET_TOOLBAR_MENU_ITEMS = 13; public static final int COMMAND_REMOVE_ANNOTATIONS = 14; - public static final int COMMAND_SET_MEASUREMENT_SCALE = 17; - public static final int COMMAND_SET_MEASUREMENT_PRECISION = 16; + public static final int COMMAND_GET_CONFIGURATION = 18; + public static final int COMMAND_SET_TOOLBAR = 19; + public static final int COMMAND_SET_MEASUREMENT_VALUE_CONFIGURATIONS = 21; + public static final int COMMAND_GET_MEASUREMENT_VALUE_CONFIGURATIONS = 22; private final CompositeDisposable annotationDisposables = new CompositeDisposable(); @@ -113,8 +119,10 @@ public Map getCommandsMap() { commandMap.put("getAllAnnotations", COMMAND_GET_ALL_ANNOTATIONS); commandMap.put("removeFragment", COMMAND_REMOVE_FRAGMENT); commandMap.put("setToolbarMenuItems", COMMAND_SET_TOOLBAR_MENU_ITEMS); - commandMap.put("setMeasurementScale", COMMAND_SET_MEASUREMENT_SCALE); - commandMap.put("setMeasurementPrecision", COMMAND_SET_MEASUREMENT_PRECISION); + commandMap.put("setMeasurementValueConfigurations", COMMAND_SET_MEASUREMENT_VALUE_CONFIGURATIONS); + commandMap.put("getMeasurementValueConfigurations", COMMAND_GET_MEASUREMENT_VALUE_CONFIGURATIONS); + commandMap.put("getConfiguration", COMMAND_GET_CONFIGURATION); + commandMap.put("setToolbar", COMMAND_SET_TOOLBAR); return commandMap; } @@ -126,7 +134,20 @@ public void setFragmentTag(PdfView view, @NonNull String fragmentTag) { @ReactProp(name = "configuration") public void setConfiguration(PdfView view, @NonNull ReadableMap configuration) { ConfigurationAdapter configurationAdapter = new ConfigurationAdapter(view.getContext(), configuration); - view.setConfiguration(configurationAdapter.build()); + PdfActivityConfiguration configurationBuild = configurationAdapter.build(); + view.setInitialConfiguration(configurationBuild); + // If there are pending toolbar items, we need to apply them. + if (view.getPendingToolbarItems() != null) { + ToolbarMenuItemsAdapter newConfigurations = new ToolbarMenuItemsAdapter(configurationBuild, view.getPendingToolbarItems(), view.getInitialConfiguration()); + view.setConfiguration(newConfigurations.build()); + } else { + view.setConfiguration(configurationBuild); + } + view.setDocumentPassword(configuration.getString("documentPassword")); + // Although MeasurementValueConfigurations is specified as part of Configuration, it is configured separately on the Android SDK + if (configuration.getArray("measurementValueConfigurations") != null) { + view.setMeasurementValueConfigurations(configuration.getArray("measurementValueConfigurations")); + } } @ReactProp(name = "annotationPresets") @@ -147,6 +168,36 @@ public void setPageIndex(PdfView view, int pageIndex) { view.setPageIndex(pageIndex); } + @ReactProp(name = "toolbar") + public void setToolbar(@NonNull final PdfView view, @NonNull ReadableMap toolbar) { + ReadableMap toolbarMenuItems = toolbar.getMap("toolbarMenuItems"); + ArrayList buttons = toolbarMenuItems.getArray("buttons").toArrayList(); + WritableArray stockToolbarItems = new WritableNativeArray(); + ArrayList customToolbarItems = new ArrayList(); + for(int i = 0; i < buttons.size(); i++) { + Object item = buttons.get(i); + if (item instanceof String) { + stockToolbarItems.pushString((String)item); + } else if (item instanceof HashMap) { + ((HashMap) item).put("index", i); + customToolbarItems.add(item); + } + } + if (stockToolbarItems != null) { + PdfActivityConfiguration currentConfiguration = view.getConfiguration(); + ToolbarMenuItemsAdapter newConfigurations = new ToolbarMenuItemsAdapter(currentConfiguration, stockToolbarItems, view.getInitialConfiguration()); + // If the initial config is null, it means that the user-provided config has not been applied yet, so we set toolbar items as pending. + if (view.getInitialConfiguration() == null) { + view.setPendingToolbarItems(stockToolbarItems); + } else { + view.setConfiguration(newConfigurations.build()); + } + } + if (customToolbarItems != null) { + view.setCustomToolbarItems(customToolbarItems); + } + } + @ReactProp(name = "disableDefaultActionForTappedAnnotations") public void setDisableDefaultActionForTappedAnnotations(PdfView view, boolean disableDefaultActionForTappedAnnotations) { view.setDisableDefaultActionForTappedAnnotations(disableDefaultActionForTappedAnnotations); @@ -192,8 +243,20 @@ public void setSelectedFontName(@NonNull final PdfView view, @Nullable final Str public void setToolbarMenuItems(@NonNull final PdfView view, @Nullable final ReadableArray toolbarItems) { if (toolbarItems != null) { PdfActivityConfiguration currentConfiguration = view.getConfiguration(); - ToolbarMenuItemsAdapter newConfigurations = new ToolbarMenuItemsAdapter(currentConfiguration, toolbarItems); - view.setConfiguration(newConfigurations.build()); + ToolbarMenuItemsAdapter newConfigurations = new ToolbarMenuItemsAdapter(currentConfiguration, toolbarItems, view.getInitialConfiguration()); + // If the initial config is null, it means that the user-provided config has not been applied yet, so we set toolbar items as pending. + if (view.getInitialConfiguration() == null) { + view.setPendingToolbarItems(toolbarItems); + } else { + view.setConfiguration(newConfigurations.build()); + } + } + } + + @ReactProp(name = "measurementValueConfigurations") + public void setMeasurementValueConfigurations(@NonNull final PdfView view, @Nullable final ReadableArray measurementValueConfigs) { + if (measurementValueConfigs != null) { + view.setMeasurementValueConfigurations(measurementValueConfigs); } } @@ -324,28 +387,40 @@ public void accept(List annotations) { setToolbarMenuItems(root,args.getArray(0)); } break; - case COMMAND_SET_MEASUREMENT_SCALE: + case COMMAND_SET_MEASUREMENT_VALUE_CONFIGURATIONS: + if (args != null && args.size() == 2) { + final int requestId = args.getInt(0); + setMeasurementValueConfigurations(root, args.getArray(1)); + root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, true)); + } + break; + case COMMAND_GET_MEASUREMENT_VALUE_CONFIGURATIONS: if (args != null) { final int requestId = args.getInt(0); try { - boolean result = root.setMeasurementScale(args.getMap(1)); + JSONObject result = root.getMeasurementValueConfigurations(); root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, result)); } catch (Exception e) { root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, e)); } } break; - case COMMAND_SET_MEASUREMENT_PRECISION: + case COMMAND_GET_CONFIGURATION: if (args != null) { final int requestId = args.getInt(0); try { - boolean result = root.setMeasurementPrecision(args.getString(1)); + JSONObject result = root.convertConfiguration(); root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, result)); } catch (Exception e) { root.getEventDispatcher().dispatchEvent(new PdfViewDataReturnedEvent(root.getId(), requestId, e)); } } break; + case COMMAND_SET_TOOLBAR: + if (args != null && args.size() == 1) { + setToolbar(root,args.getMap(0)); + } + break; } } diff --git a/android/src/main/java/com/pspdfkit/react/TestingModule.java b/android/src/main/java/com/pspdfkit/react/TestingModule.java index 398186c3..82b2923a 100644 --- a/android/src/main/java/com/pspdfkit/react/TestingModule.java +++ b/android/src/main/java/com/pspdfkit/react/TestingModule.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/ToolbarMenuItemsAdapter.java b/android/src/main/java/com/pspdfkit/react/ToolbarMenuItemsAdapter.java index f9ce0e04..30cf38b3 100644 --- a/android/src/main/java/com/pspdfkit/react/ToolbarMenuItemsAdapter.java +++ b/android/src/main/java/com/pspdfkit/react/ToolbarMenuItemsAdapter.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2022-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2022-2024 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. @@ -43,7 +43,11 @@ public class ToolbarMenuItemsAdapter { * @param currentConfiguration The current configuration. * @param toolbarItems The toolbar items to be customized. */ - public ToolbarMenuItemsAdapter(@NonNull final PdfActivityConfiguration currentConfiguration, @NonNull final ReadableArray toolbarItems) { + public ToolbarMenuItemsAdapter(@NonNull final PdfActivityConfiguration currentConfiguration, @NonNull final ReadableArray toolbarItems, PdfActivityConfiguration initialConfiguration) { + // Initial config is used as the source for the user-defined config. If not available, use the current config. + if (initialConfiguration == null) { + initialConfiguration = currentConfiguration; + } PdfActivityConfiguration.Builder configurationBuilder = new PdfActivityConfiguration.Builder(currentConfiguration); PdfActivityConfiguration.Builder configuration = disableDefaultToolbarItems(configurationBuilder); @@ -51,57 +55,57 @@ public ToolbarMenuItemsAdapter(@NonNull final PdfActivityConfiguration currentCo String toolbarItem = toolbarItems.getString(i); switch (toolbarItem) { case TOOLBAR_ITEM_SEARCH: - if (currentConfiguration.isSearchEnabled()) { + if (initialConfiguration.isSearchEnabled()) { configuration.enableSearch(); } break; case TOOLBAR_ITEM_READER_VIEW: - if (currentConfiguration.isReaderViewEnabled()) { + if (initialConfiguration.isReaderViewEnabled()) { configuration.enableReaderView(true); } break; case TOOLBAR_ITEM_ANNOTATIONS: - if (currentConfiguration.getConfiguration().isAnnotationEditingEnabled()) { + if (initialConfiguration.getConfiguration().isAnnotationEditingEnabled()) { configuration.enableAnnotationEditing(); } break; case TOOLBAR_ITEM_THUMBNAILS: - if (currentConfiguration.isThumbnailGridEnabled()) { + if (initialConfiguration.isThumbnailGridEnabled()) { configuration.showThumbnailGrid(); } break; case TOOLBAR_ITEM_SHARE: - if (!currentConfiguration.getConfiguration().getEnabledShareFeatures().isEmpty()) { + if (!initialConfiguration.getConfiguration().getEnabledShareFeatures().isEmpty()) { configuration.setEnabledShareFeatures(ShareFeatures.all()); } break; case TOOLBAR_ITEM_SETTINGS: - if (currentConfiguration.isSettingsItemEnabled()) { + if (initialConfiguration.isSettingsItemEnabled()) { configuration.showSettingsMenu(); } break; case TOOLBAR_ITEM_OUTLINE: - if (currentConfiguration.isOutlineEnabled()) { + if (initialConfiguration.isOutlineEnabled()) { configuration.enableOutline(); } break; case TOOLBAR_ITEM_BOOKMARKS: - if (currentConfiguration.isBookmarkListEnabled()) { + if (initialConfiguration.isBookmarkListEnabled()) { configuration.enableBookmarkList(); } break; case TOOLBAR_ITEM_PRINT: - if (currentConfiguration.isPrintingEnabled()) { + if (initialConfiguration.isPrintingEnabled()) { configuration.enablePrinting(); } break; case TOOLBAR_ITEM_ANNOTATION_LIST: - if (currentConfiguration.isAnnotationListEnabled()) { + if (initialConfiguration.isAnnotationListEnabled()) { configuration.enableAnnotationList(); } break; case TOOLBAR_ITEM_DOCUMENT_INFO_VIEW: - if (currentConfiguration.isDocumentInfoViewEnabled()) { + if (initialConfiguration.isDocumentInfoViewEnabled()) { configuration.enableDocumentInfoView(); } break; diff --git a/android/src/main/java/com/pspdfkit/react/events/CustomToolbarButtonTappedEvent.kt b/android/src/main/java/com/pspdfkit/react/events/CustomToolbarButtonTappedEvent.kt new file mode 100644 index 00000000..dd554b05 --- /dev/null +++ b/android/src/main/java/com/pspdfkit/react/events/CustomToolbarButtonTappedEvent.kt @@ -0,0 +1,30 @@ +package com.pspdfkit.react.events + +import androidx.annotation.IdRes +import com.facebook.react.bridge.Arguments +import com.facebook.react.uimanager.events.Event +import com.facebook.react.uimanager.events.RCTEventEmitter + +class CustomToolbarButtonTappedEvent: Event { + + private var buttonId: String? = null + + constructor(@IdRes viewId: Int, buttonId: String) : super(viewId) { + this.buttonId = buttonId + } + + override fun getEventName(): String? { + return EVENT_NAME + } + + override fun dispatch(rctEventEmitter: RCTEventEmitter) { + val eventData = Arguments.createMap() + eventData.putString("id", buttonId) + rctEventEmitter.receiveEvent(viewTag, eventName, eventData) + } + + companion object { + @kotlin.jvm.JvmField + var EVENT_NAME = "customToolbarButtonTapped" + } +} \ No newline at end of file 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 0c191004..09e50858 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationChangedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. 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 8f43df74..00ded923 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewDataReturnedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewDataReturnedEvent.java index 80fec444..55eb04e3 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewDataReturnedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewDataReturnedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadFailedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadFailedEvent.java index 13541b99..1d1d166d 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadFailedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadFailedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadedEvent.java index 42a3cf65..d0e62874 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSaveFailedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSaveFailedEvent.java index c2c1e8cc..eb0b95f5 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSaveFailedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSaveFailedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java index 2c2b5275..a8e8da30 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewNavigationButtonClickedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewNavigationButtonClickedEvent.java index 8fbce541..90de1d29 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewNavigationButtonClickedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewNavigationButtonClickedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/events/PdfViewStateChangedEvent.java b/android/src/main/java/com/pspdfkit/react/events/PdfViewStateChangedEvent.java index 290184ae..d0eacf38 100644 --- a/android/src/main/java/com/pspdfkit/react/events/PdfViewStateChangedEvent.java +++ b/android/src/main/java/com/pspdfkit/react/events/PdfViewStateChangedEvent.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/helper/ColorHelper.java b/android/src/main/java/com/pspdfkit/react/helper/ColorHelper.java index 5b2a6b64..03e7a135 100644 --- a/android/src/main/java/com/pspdfkit/react/helper/ColorHelper.java +++ b/android/src/main/java/com/pspdfkit/react/helper/ColorHelper.java @@ -5,7 +5,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/helper/ConversionHelpers.java b/android/src/main/java/com/pspdfkit/react/helper/ConversionHelpers.java index 2b4b6a10..eb475790 100644 --- a/android/src/main/java/com/pspdfkit/react/helper/ConversionHelpers.java +++ b/android/src/main/java/com/pspdfkit/react/helper/ConversionHelpers.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/helper/DocumentJsonDataProvider.java b/android/src/main/java/com/pspdfkit/react/helper/DocumentJsonDataProvider.java index f341a6aa..724ed805 100644 --- a/android/src/main/java/com/pspdfkit/react/helper/DocumentJsonDataProvider.java +++ b/android/src/main/java/com/pspdfkit/react/helper/DocumentJsonDataProvider.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java b/android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java index e1066215..5247483e 100644 --- a/android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java +++ b/android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/helper/MeasurementHelper.java b/android/src/main/java/com/pspdfkit/react/helper/MeasurementHelper.java deleted file mode 100644 index 3105a85f..00000000 --- a/android/src/main/java/com/pspdfkit/react/helper/MeasurementHelper.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * ConversionHelpers.java - * - * PSPDFKit - * - * Copyright © 2021-2023 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. - * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. - * This notice may not be removed from this file. - */ - - -package com.pspdfkit.react.helper; - -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableMapKeySetIterator; -import com.pspdfkit.annotations.measurements.MeasurementPrecision; -import com.pspdfkit.annotations.measurements.Scale; -import com.pspdfkit.document.PdfDocument; - -import javax.annotation.Nullable; - -public class MeasurementHelper { - - public static MeasurementPrecision getPrecision(@Nullable String precisionString) { - if (precisionString == null) { - return MeasurementPrecision.TWO_DP; - } - - switch (precisionString.toLowerCase()) { - case "whole": - return MeasurementPrecision.WHOLE; - case "onedp": - return MeasurementPrecision.ONE_DP; - case "threedp": - return MeasurementPrecision.THREE_DP; - case "fourdp": - return MeasurementPrecision.FOUR_DP; - - default: - return MeasurementPrecision.TWO_DP; - } - } - - private static Scale.UnitFrom parseScaleUnitFrom(@Nullable String stringUnit) { - if (stringUnit == null) { - return Scale.UnitFrom.IN; - } - switch (stringUnit.toLowerCase()) { - case "mm": - return Scale.UnitFrom.MM; - case "cm": - return Scale.UnitFrom.CM; - case "pt": - return Scale.UnitFrom.PT; - default: - return Scale.UnitFrom.IN; - } - } - - private static Scale.UnitTo parseScaleUnitTo(String stringUnit) { - if (stringUnit == null) { - return Scale.UnitTo.IN; - } - switch (stringUnit.toLowerCase()) { - case "mm": - return Scale.UnitTo.MM; - case "cm": - return Scale.UnitTo.CM; - case "pt": - return Scale.UnitTo.PT; - case "ft": - return Scale.UnitTo.FT; - case "m": - return Scale.UnitTo.M; - case "yd": - return Scale.UnitTo.YD; - case "km": - return Scale.UnitTo.KM; - case "mi": - return Scale.UnitTo.MI; - default: - return Scale.UnitTo.IN; - } - } - - public static Scale getScale(ReadableMap rawData) { - Scale.UnitFrom unitFrom = Scale.UnitFrom.IN; - Scale.UnitTo unitTo = Scale.UnitTo.IN; - double valueFrom = 1.0; - double valueTo = 1.0; - - ReadableMapKeySetIterator iterator = rawData.keySetIterator(); - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - switch (key) { - case "unitFrom": - unitFrom = parseScaleUnitFrom(rawData.getString(key)); - break; - case "unitTo": - unitTo = parseScaleUnitTo(rawData.getString(key)); - break; - case "valueFrom": - valueFrom = rawData.getDouble(key); - break; - case "valueTo": - valueTo = rawData.getDouble(key); - break; - } - } - - return new Scale((float) valueFrom, unitFrom, (float) valueTo, unitTo); - } - - public static void setConfig(@Nullable ReadableMap configuration, @Nullable PdfDocument document) { - if(configuration == null || document == null) { - return; - } - - if (configuration.hasKey("measurementScale")) { - document.setMeasurementScale(MeasurementHelper.getScale(configuration)); - } - if (configuration.hasKey("measurementPrecision")) { - document.setMeasurementPrecision(MeasurementHelper.getPrecision(configuration.getString("measurementPrecision"))); - } - } -} diff --git a/android/src/main/java/com/pspdfkit/react/helper/MeasurementsHelper.kt b/android/src/main/java/com/pspdfkit/react/helper/MeasurementsHelper.kt new file mode 100644 index 00000000..65ef0b4d --- /dev/null +++ b/android/src/main/java/com/pspdfkit/react/helper/MeasurementsHelper.kt @@ -0,0 +1,199 @@ +package com.pspdfkit.react.helper + +import com.pspdfkit.annotations.measurements.MeasurementPrecision +import com.pspdfkit.annotations.measurements.MeasurementValueConfiguration +import com.pspdfkit.annotations.measurements.Scale +import com.pspdfkit.ui.PdfFragment + +class MeasurementsHelper { + + companion object { + + /** + * Adds a new measurement configuration to the document. + * + * @param pdfFragment The [PdfFragment] to which the measurement configuration should be added. + * @param configurations The measurement configuration to add. + */ + @JvmStatic + fun addMeasurementConfiguration(pdfFragment: PdfFragment, configurations : Map) { + val measurementValueConfiguration = convertMeasurementConfiguration(configurations) + val addToUndo = (configurations["addToUndo"] as Boolean?) ?: false + pdfFragment.measurementValueConfigurationEditor?.add(measurementValueConfiguration,addToUndo) + val isSelected = (configurations["isSelected"] as Boolean?) ?: false + if (isSelected) { + pdfFragment.setSelectedMeasurementValueConfiguration(measurementValueConfiguration); + } + } + + /** + * Removes a measurement configuration from the document. + * + * @param pdfFragment The [PdfFragment] from which the measurement configuration should be removed. + * @param configurations The measurement configuration to remove. + */ + @JvmStatic + fun removeMeasurementConfiguration(pdfFragment: PdfFragment, configurations :Map) { + val measurementValueConfiguration = convertMeasurementConfiguration(configurations["configuration"] as Map) + val deleteAssociatedAnnotations = configurations["deleteAssociatedAnnotations"] as Boolean + val addToUndoStack = configurations["addToUndo"] as Boolean + pdfFragment.measurementValueConfigurationEditor?.remove(measurementValueConfiguration,deleteAssociatedAnnotations,addToUndoStack) + } + + /** + * Returns the measurement configurations for the document. + * + * @param pdfFragment The [PdfFragment] from which the measurement configurations should be retrieved. + * @return The measurement configurations for the document. + */ + @JvmStatic + fun getMeasurementConfigurations(pdfFragment: PdfFragment) : List> { + return pdfFragment.measurementValueConfigurationEditor?.configurations?.map { reverseMeasurementConfiguration(it) } ?: emptyList() + } + + /** + * Modifies a measurement configuration in the document. + * + * @param pdfFragment The [PdfFragment] in which the measurement configuration should be modified. + * @param args The arguments for the modification. + */ + @JvmStatic + fun modifyMeasurementConfiguration(pdfFragment: PdfFragment, args : Map) { + val newMeasurementValueConfiguration = convertMeasurementConfiguration(args["newConfiguration"] as Map?) + val oldMeasurementValueConfiguration = convertMeasurementConfiguration(args["oldConfiguration"] as Map?) + val modifyAssociatedAnnotations = args["modifyAssociatedAnnotations"] as Boolean + val addToUndoStack = args["addToUndo"] as Boolean + pdfFragment.measurementValueConfigurationEditor?.modify(oldMeasurementValueConfiguration,newMeasurementValueConfiguration, + modifyAssociatedAnnotations,addToUndoStack) + } + + /** + * Converts a measurement configuration from a map to a [MeasurementValueConfiguration]. + * + * @param measurementConfigurations The map representation of the measurement configuration. + * @return The [MeasurementValueConfiguration] representation of the measurement configuration. + */ + @JvmStatic + fun convertMeasurementConfiguration(measurementConfigurations: Map?): MeasurementValueConfiguration { + val scale = + convertScale(measurementConfigurations?.get("scale") as Map?) + val precision = + convertPrecision(measurementConfigurations?.get("precision") as String?) + val name = (measurementConfigurations?.get("name") as String?) ?: "Unknown" + if (scale == null) { + throw IllegalArgumentException("Invalid scale") + } + if (precision == null) { + throw IllegalArgumentException("Invalid precision") + } + return MeasurementValueConfiguration(name, scale, precision) + } + private fun reverseMeasurementConfiguration(measurementValueConfiguration: MeasurementValueConfiguration): Map { + return mapOf( + "name" to measurementValueConfiguration.name, + "scale" to reverseScale(measurementValueConfiguration.scale), + "precision" to reversePrecision(measurementValueConfiguration.precision) + ) + } + + private fun convertScale(scale: Map?): Scale? { + if (scale == null) { + return null + } + val fromValue: Double = requireNotNull(scale["valueFrom"] as Double) + val toValue: Double = requireNotNull(scale["valueTo"] as Double) + val unitFromValue: String = requireNotNull(scale["unitFrom"] as String) + val unitToValue: String = requireNotNull(scale["unitTo"] as String) + + val unitFrom: Scale.UnitFrom = convertUnitFrom(unitFromValue) + val unitTo: Scale.UnitTo = convertUnitTo(unitToValue) + return Scale(fromValue.toFloat(), unitFrom, toValue.toFloat(), unitTo) + } + + private fun convertUnitFrom(unitFrom: String): Scale.UnitFrom { + return when (unitFrom) { + "cm" -> Scale.UnitFrom.CM + "inch" -> Scale.UnitFrom.IN + "pt" -> Scale.UnitFrom.PT + "mm" -> Scale.UnitFrom.MM + else -> Scale.UnitFrom.CM + } + } + + private fun convertUnitTo(unitTo: String): Scale.UnitTo { + return when (unitTo) { + "cm" -> Scale.UnitTo.CM + "inch" -> Scale.UnitTo.IN + "m" -> Scale.UnitTo.M + "ft" -> Scale.UnitTo.FT + "mm" -> Scale.UnitTo.MM + "km" -> Scale.UnitTo.KM + "mi" -> Scale.UnitTo.MI + "yd" -> Scale.UnitTo.YD + else -> Scale.UnitTo.CM + } + } + + private fun reverseScale(scale: Scale): Map { + return mapOf( + "valueFrom" to scale.valueFrom.toDouble(), + "valueTo" to scale.valueTo.toDouble(), + "unitFrom" to reverseUnitFrom(scale.unitFrom), + "unitTo" to reverseUnitTo(scale.unitTo) + ) + } + + private fun reverseUnitFrom(unitFrom: Scale.UnitFrom): String { + return when (unitFrom) { + Scale.UnitFrom.CM -> "cm" + Scale.UnitFrom.IN -> "inch" + Scale.UnitFrom.PT -> "pt" + Scale.UnitFrom.MM -> "mm" + } + } + + private fun reverseUnitTo(unitTo: Scale.UnitTo): String { + return when (unitTo) { + Scale.UnitTo.CM -> "cm" + Scale.UnitTo.IN -> "inch" + Scale.UnitTo.M -> "m" + Scale.UnitTo.FT -> "ft" + Scale.UnitTo.MM -> "mm" + Scale.UnitTo.KM -> "km" + Scale.UnitTo.MI -> "mi" + Scale.UnitTo.YD -> "yd" + Scale.UnitTo.PT -> "pt" + } + } + + private fun convertPrecision(precision: String?): MeasurementPrecision? { + if (precision == null) { + return null + } + val measurementPrecision = when (precision) { + "oneDP" -> MeasurementPrecision.ONE_DP + "twoDP" -> MeasurementPrecision.TWO_DP + "threeDP" -> MeasurementPrecision.THREE_DP + "fourDP" -> MeasurementPrecision.FOUR_DP + "whole" -> MeasurementPrecision.WHOLE + else -> MeasurementPrecision.TWO_DP + } + return measurementPrecision + } + + private fun reversePrecision(precision: MeasurementPrecision): String { + return when (precision) { + MeasurementPrecision.ONE_DP -> "oneDP" + MeasurementPrecision.TWO_DP -> "twoDP" + MeasurementPrecision.THREE_DP -> "threeDP" + MeasurementPrecision.FOUR_DP -> "fourDP" + MeasurementPrecision.WHOLE -> "whole" + MeasurementPrecision.WHOLE_INCH -> "wholeInch" + MeasurementPrecision.HALVES_INCH -> "halvesInch" + MeasurementPrecision.QUARTERS_INCH -> "quartersInch" + MeasurementPrecision.EIGHTHS_INCH -> "eighthsInch" + MeasurementPrecision.SIXTEENTHS_INCH -> "sixteenthsInch" + } + } + } +} \ No newline at end of file diff --git a/android/src/main/java/com/pspdfkit/react/helper/RNConfigurationHelper.java b/android/src/main/java/com/pspdfkit/react/helper/RNConfigurationHelper.java index 3865a478..f41149b8 100644 --- a/android/src/main/java/com/pspdfkit/react/helper/RNConfigurationHelper.java +++ b/android/src/main/java/com/pspdfkit/react/helper/RNConfigurationHelper.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/helper/RNFileHelper.java b/android/src/main/java/com/pspdfkit/react/helper/RNFileHelper.java index 144cb77a..d7f6b347 100644 --- a/android/src/main/java/com/pspdfkit/react/helper/RNFileHelper.java +++ b/android/src/main/java/com/pspdfkit/react/helper/RNFileHelper.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2017-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2017-2024 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. diff --git a/android/src/main/java/com/pspdfkit/react/menu/ReactGroupingRule.java b/android/src/main/java/com/pspdfkit/react/menu/ReactGroupingRule.java index e6c7ce5e..fdd576fa 100644 --- a/android/src/main/java/com/pspdfkit/react/menu/ReactGroupingRule.java +++ b/android/src/main/java/com/pspdfkit/react/menu/ReactGroupingRule.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/views/MenuItemListener.kt b/android/src/main/java/com/pspdfkit/views/MenuItemListener.kt new file mode 100644 index 00000000..81a5def9 --- /dev/null +++ b/android/src/main/java/com/pspdfkit/views/MenuItemListener.kt @@ -0,0 +1,29 @@ +package com.pspdfkit.views + +import android.content.Context +import android.util.Log +import android.view.MenuItem +import androidx.annotation.NonNull +import com.facebook.react.uimanager.events.EventDispatcher +import com.pspdfkit.react.events.CustomToolbarButtonTappedEvent + +class MenuItemListener: MenuItem.OnMenuItemClickListener { + + private var parent: PdfView? = null + private var eventDispatcher: EventDispatcher? = null + private var context: Context? = null; + + constructor(parent: PdfView, eventDispatcher: EventDispatcher, context: Context) { + this.parent = parent + this.eventDispatcher = eventDispatcher + this.context = context + } + + override fun onMenuItemClick(menuItem: MenuItem): Boolean { + val resourceName: String? = context?.resources?.getResourceEntryName(menuItem.itemId) + if (resourceName != null) { + eventDispatcher!!.dispatchEvent(parent?.let { CustomToolbarButtonTappedEvent(it.id, resourceName) }) + } + return false + } +} \ 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 1e7d2974..31093c15 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfView.java +++ b/android/src/main/java/com/pspdfkit/views/PdfView.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. @@ -13,6 +13,7 @@ package com.pspdfkit.views; +import static com.pspdfkit.configuration.signatures.SignatureSavingStrategy.*; import static com.pspdfkit.react.helper.ConversionHelpers.getAnnotationTypeFromString; import android.annotation.SuppressLint; @@ -41,6 +42,7 @@ import com.pspdfkit.annotations.configuration.AnnotationConfiguration; import com.pspdfkit.annotations.configuration.FreeTextAnnotationConfiguration; import com.pspdfkit.configuration.activity.PdfActivityConfiguration; +import com.pspdfkit.configuration.sharing.ShareFeatures; import com.pspdfkit.document.DocumentSaveOptions; import com.pspdfkit.document.ImageDocument; import com.pspdfkit.document.ImageDocumentLoader; @@ -56,15 +58,20 @@ import com.pspdfkit.listeners.SimpleDocumentListener; import com.pspdfkit.react.R; import com.pspdfkit.react.events.PdfViewAnnotationChangedEvent; +import com.pspdfkit.react.ConfigurationAdapter; import com.pspdfkit.react.events.PdfViewAnnotationTappedEvent; import com.pspdfkit.react.events.PdfViewDataReturnedEvent; import com.pspdfkit.react.events.PdfViewDocumentLoadFailedEvent; +import com.pspdfkit.react.events.PdfViewDocumentLoadedEvent; import com.pspdfkit.react.events.PdfViewDocumentSaveFailedEvent; import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; import com.pspdfkit.react.events.PdfViewNavigationButtonClickedEvent; +import com.pspdfkit.react.events.CustomToolbarButtonTappedEvent; import com.pspdfkit.react.events.PdfViewStateChangedEvent; import com.pspdfkit.react.helper.DocumentJsonDataProvider; -import com.pspdfkit.react.helper.MeasurementHelper; +import com.pspdfkit.react.helper.MeasurementsHelper; +import com.pspdfkit.signatures.storage.DatabaseSignatureStorage; +import com.pspdfkit.signatures.storage.SignatureStorage; import com.pspdfkit.react.helper.PSPDFKitUtils; import com.pspdfkit.ui.DocumentDescriptor; import com.pspdfkit.ui.PdfFragment; @@ -88,7 +95,6 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import java.util.concurrent.Callable; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Completable; @@ -102,9 +108,6 @@ import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.BehaviorSubject; - -import static com.pspdfkit.react.helper.ConversionHelpers.getAnnotationTypeFromString; - /** * This view displays a {@link com.pspdfkit.ui.PdfFragment} and all associated toolbars. */ @@ -124,13 +127,18 @@ public class PdfView extends FrameLayout { private Disposable documentOpeningDisposable; private PdfDocument document; private String documentPath; + private String documentPassword; private int pageIndex = 0; + private PdfActivityConfiguration initialConfiguration; + private ReadableArray pendingToolbarItems; private boolean isActive = true; private PdfViewModeController pdfViewModeController; private PdfViewDocumentListener pdfViewDocumentListener; + private MenuItemListener menuItemListener; + @NonNull private CompositeDisposable pendingFragmentActions = new CompositeDisposable(); @@ -164,6 +172,9 @@ public class PdfView extends FrameLayout { @Nullable private Map annotationsConfigurations; + @Nullable + private ReadableArray measurementValueConfigurations; + public PdfView(@NonNull Context context) { super(context); init(); @@ -210,6 +221,7 @@ public void inject(FragmentManager fragmentManager, EventDispatcher eventDispatc this.eventDispatcher = eventDispatcher; pdfViewDocumentListener = new PdfViewDocumentListener(this, eventDispatcher); + menuItemListener = new MenuItemListener(this, eventDispatcher, getContext()); } public void setFragmentTag(String fragmentTag) { @@ -217,6 +229,22 @@ public void setFragmentTag(String fragmentTag) { setupFragment(); } + public void setInitialConfiguration(PdfActivityConfiguration configuration) { + this.initialConfiguration = configuration; + } + + public PdfActivityConfiguration getInitialConfiguration() { + return this.initialConfiguration; + } + + public void setPendingToolbarItems(ReadableArray toolbarItems) { + this.pendingToolbarItems = toolbarItems; + } + + public ReadableArray getPendingToolbarItems() { + return this.pendingToolbarItems; + } + public void setConfiguration(PdfActivityConfiguration configuration) { if (configuration != null && !configuration.equals(this.configuration)) { // The configuration changed, recreate the fragment. @@ -232,11 +260,24 @@ public PdfActivityConfiguration getConfiguration() { return configuration; } + public void setCustomToolbarItems(final ArrayList toolbarItems) { + pendingFragmentActions.add(getCurrentPdfUiFragment() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(pdfUiFragment -> { + ((ReactPdfUiFragment) pdfUiFragment).setCustomToolbarItems(toolbarItems, menuItemListener); + + })); + } + public void setAnnotationConfiguration(final Map annotationsConfigurations) { this.annotationsConfigurations = annotationsConfigurations; setupFragment(); } + public void setDocumentPassword(@Nullable String documentPassword) { + this.documentPassword = documentPassword; + } + public void setDocument(@Nullable String documentPath) { if (documentPath == null) { this.document = null; @@ -273,7 +314,7 @@ public void setDocument(@Nullable String documentPath) { eventDispatcher.dispatchEvent(new PdfViewDocumentLoadFailedEvent(getId(), throwable.getMessage())); }); } else { - documentOpeningDisposable = PdfDocumentLoader.openDocumentAsync(getContext(), Uri.parse(documentPath)) + documentOpeningDisposable = PdfDocumentLoader.openDocumentAsync(getContext(), Uri.parse(documentPath), documentPassword) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(pdfDocument -> { @@ -553,6 +594,18 @@ public void onDocumentLoaded(@NonNull PdfDocument document) { } } } + + // Add Measurement configuration + if (this.measurementValueConfigurations != null) { + this.applyMeasurementValueConfigurations(pdfFragment, this.measurementValueConfigurations); + } + + // Setup SignatureDatabase if SignatureSaving is enabled. + if (pdfFragment.getConfiguration().getSignatureSavingStrategy() == ALWAYS_SAVE || + pdfFragment.getConfiguration().getSignatureSavingStrategy() == SAVE_IF_SELECTED) { + final SignatureStorage storage = DatabaseSignatureStorage.withName(getContext(), "SignatureDatabase"); + pdfFragment.setSignatureStorage(storage); + } } public void removeFragment(boolean makeInactive) { @@ -607,19 +660,6 @@ void updateState(int pageIndex) { } } - public void setMeasurementConfiguration(@NonNull ReadableMap measurementConfiguration) { - if (fragment != null) { - PdfDocument document = fragment.getDocument(); - if(document != null) { - document.setMeasurementPrecision(MeasurementHelper.getPrecision(measurementConfiguration.getString("precision"))); - ReadableMap scaleConfig = measurementConfiguration.getMap("scale"); - if(scaleConfig != null) { - document.setMeasurementScale(MeasurementHelper.getScale(scaleConfig)); - } - } - } - } - public EventDispatcher getEventDispatcher() { return eventDispatcher; } @@ -841,6 +881,50 @@ public Maybe setFormFieldValue(@NonNull String formElementName, @NonNul }); } + public JSONObject convertConfiguration() { + try { + JSONObject config = new JSONObject(); + config.put("scrollDirection", ConfigurationAdapter.getStringValueForConfigurationItem(configuration.getConfiguration().getScrollDirection())); + config.put("pageTransition", ConfigurationAdapter.getStringValueForConfigurationItem(configuration.getConfiguration().getScrollMode())); + config.put("enableTextSelection", configuration.getConfiguration().isTextSelectionEnabled()); + config.put("autosaveEnabled", configuration.getConfiguration().isAutosaveEnabled()); + config.put("disableAutomaticSaving", !configuration.getConfiguration().isAutosaveEnabled()); + config.put("signatureSavingStrategy", ConfigurationAdapter.getStringValueForConfigurationItem(configuration.getConfiguration().getSignatureSavingStrategy())); + + config.put("pageMode", ConfigurationAdapter.getStringValueForConfigurationItem(configuration.getConfiguration().getLayoutMode())); + config.put("firstPageAlwaysSingle", configuration.getConfiguration().isFirstPageAlwaysSingle()); + config.put("showPageLabels", configuration.isShowPageLabels()); + config.put("documentLabelEnabled", configuration.isShowDocumentTitleOverlayEnabled()); + config.put("spreadFitting", ConfigurationAdapter.getStringValueForConfigurationItem(configuration.getConfiguration().getFitMode())); + config.put("invertColors", configuration.getConfiguration().isInvertColors()); + config.put("androidGrayScale", configuration.getConfiguration().isToGrayscale()); + + config.put("userInterfaceViewMode", ConfigurationAdapter.getStringValueForConfigurationItem(configuration.getUserInterfaceViewMode())); + config.put("inlineSearch", configuration.getSearchType() == PdfActivityConfiguration.SEARCH_INLINE ? true : false); + config.put("immersiveMode", configuration.isImmersiveMode()); + config.put("toolbarTitle", configuration.getActivityTitle()); + config.put("androidShowSearchAction", configuration.isSearchEnabled()); + config.put("androidShowOutlineAction", configuration.isOutlineEnabled()); + config.put("androidShowBookmarksAction", configuration.isBookmarkListEnabled()); + config.put("androidShowShareAction", configuration.getConfiguration().getEnabledShareFeatures() == ShareFeatures.all() ? true : false); + config.put("androidShowPrintAction", configuration.isPrintingEnabled()); + config.put("androidShowDocumentInfoView", configuration.isDocumentInfoViewEnabled()); + config.put("androidShowSettingsMenu", configuration.isSettingsItemEnabled()); + + config.put("showThumbnailBar", ConfigurationAdapter.getStringValueForConfigurationItem(configuration.getThumbnailBarMode())); + config.put("androidShowThumbnailGridAction", configuration.isThumbnailGridEnabled()); + + config.put("editableAnnotationTypes", ConfigurationAdapter.getStringValuesForConfigurationItems(configuration.getConfiguration().getEditableAnnotationTypes())); + config.put("enableAnnotationEditing", configuration.getConfiguration().isAnnotationEditingEnabled()); + config.put("enableFormEditing", configuration.getConfiguration().isFormEditingEnabled()); + config.put("androidShowAnnotationListAction", configuration.isAnnotationListEnabled()); + + return config; + } catch (Exception e) { + return new JSONObject(); + } + } + /** Returns the {@link PdfFragment} hosted in the current {@link PdfUiFragment}. */ private Observable getCurrentPdfFragment() { return getPdfFragment() @@ -886,42 +970,45 @@ public static Map> createDefaultEventRegistrationMa PdfViewDocumentLoadFailedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentLoadFailed") ); map.put(PdfViewNavigationButtonClickedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onNavigationButtonClicked")); + map.put(PdfViewDocumentLoadedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentLoaded")); + map.put(CustomToolbarButtonTappedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onCustomToolbarButtonTapped")); return map; } + private void applyMeasurementValueConfigurations(PdfFragment fragment, ReadableArray measurementConfigs) { + if (this.measurementValueConfigurations != null) { + for (int i = 0; i < this.measurementValueConfigurations.size(); i++) { + ReadableMap configuration = this.measurementValueConfigurations.getMap(i); + MeasurementsHelper.addMeasurementConfiguration(fragment, configuration.toHashMap()); + } + } + } + /** - * Returns the event registration map for the default events emitted by the {@link PdfView}. - * @param scaleConfig - * @return true if the scale was set, false otherwise. + * Sets the MeasurementValuesConfigurations on the current pdfFragment during setup, also saves it if fragment changes occur + * @param measurementConfigs */ - public boolean setMeasurementScale(ReadableMap scaleConfig) { - if (fragment != null) { - PdfDocument document = fragment.getDocument(); - if(document != null) { - if(scaleConfig != null) { - document.setMeasurementScale(MeasurementHelper.getScale(scaleConfig)); - return true; - } - } + public void setMeasurementValueConfigurations(ReadableArray measurementConfigs) { + this.measurementValueConfigurations = measurementConfigs; + if (fragment != null && fragment.getPdfFragment() != null) { + this.applyMeasurementValueConfigurations(fragment.getPdfFragment(), measurementConfigs); } - return false; } /** - * Returns the event registration map for the default events emitted by the {@link PdfView}. - * @param precisionString - * @return true if the precision was set, false otherwise. + * Returns the current MeasurementValuesConfigurations + * @return List of MeasurementValueConfiguration objects */ - public boolean setMeasurementPrecision(String precisionString) { - if (fragment != null) { - PdfDocument document = fragment.getDocument(); - if(document != null) { - if(precisionString != null) { - document.setMeasurementPrecision(MeasurementHelper.getPrecision(precisionString)); - return true; - } - } + public JSONObject getMeasurementValueConfigurations() throws JSONException { + + JSONObject result = new JSONObject(); + if (fragment != null && fragment.getPdfFragment() != null) { + List configs = MeasurementsHelper.getMeasurementConfigurations(fragment.getPdfFragment()); + result.put("measurementValueConfigurations", configs); + return result; } - return false; + return result; } + + } diff --git a/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java index 20d5bb42..8d612dd3 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java +++ b/android/src/main/java/com/pspdfkit/views/PdfViewDocumentListener.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. @@ -30,6 +30,7 @@ import com.pspdfkit.listeners.DocumentListener; import com.pspdfkit.react.events.PdfViewAnnotationChangedEvent; import com.pspdfkit.react.events.PdfViewAnnotationTappedEvent; +import com.pspdfkit.react.events.PdfViewDocumentLoadedEvent; import com.pspdfkit.react.events.PdfViewDocumentSaveFailedEvent; import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; import com.pspdfkit.ui.special_mode.controller.AnnotationSelectionController; @@ -63,7 +64,7 @@ public void setDisableAutomaticSaving(boolean disableAutomaticSaving) { @Override public void onDocumentLoaded(@NonNull PdfDocument pdfDocument) { - + eventDispatcher.dispatchEvent(new PdfViewDocumentLoadedEvent(parent.getId())); } @Override diff --git a/android/src/main/java/com/pspdfkit/views/PdfViewModeController.java b/android/src/main/java/com/pspdfkit/views/PdfViewModeController.java index f2deafa8..75cb19be 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfViewModeController.java +++ b/android/src/main/java/com/pspdfkit/views/PdfViewModeController.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/views/ReactMainToolbar.java b/android/src/main/java/com/pspdfkit/views/ReactMainToolbar.java index d025a307..89c2c09d 100644 --- a/android/src/main/java/com/pspdfkit/views/ReactMainToolbar.java +++ b/android/src/main/java/com/pspdfkit/views/ReactMainToolbar.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. diff --git a/android/src/main/java/com/pspdfkit/views/ReactPdfUiFragment.java b/android/src/main/java/com/pspdfkit/views/ReactPdfUiFragment.java index 3071fcf1..9fd618a0 100644 --- a/android/src/main/java/com/pspdfkit/views/ReactPdfUiFragment.java +++ b/android/src/main/java/com/pspdfkit/views/ReactPdfUiFragment.java @@ -3,7 +3,7 @@ * * PSPDFKit * - * Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + * Copyright © 2021-2024 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. @@ -13,11 +13,19 @@ package com.pspdfkit.views; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.drawable.DrawableCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -25,6 +33,10 @@ import com.pspdfkit.ui.PdfFragment; import com.pspdfkit.ui.PdfUiFragment; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + /** * This {@link PdfUiFragment} provides additional callbacks to improve integration into react native. *

@@ -35,6 +47,9 @@ */ public class ReactPdfUiFragment extends PdfUiFragment { + private ArrayList customToolbarItems = new ArrayList<>(); + private MenuItemListener menuItemListener; + @Nullable private ReactPdfUiFragmentListener reactPdfUiFragmentListener; private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks = new FragmentManager.FragmentLifecycleCallbacks() { @@ -97,4 +112,62 @@ public interface ReactPdfUiFragmentListener { /** Called when the back navigation button was clicked. */ void onNavigationButtonClicked(@NonNull PdfUiFragment pdfUiFragment); } + + private static int getCustomResourceId(@NonNull String resName, @NonNull String type, @NonNull Context context) { + int resourceId = context.getResources().getIdentifier(resName, type, context.getPackageName()); + return resourceId; + } + + void setCustomToolbarItems(@NonNull ArrayList customToolbarItems, MenuItemListener listener) { + this.customToolbarItems = customToolbarItems; + this.menuItemListener = listener; + } + + @NonNull + @Override + public List onGenerateMenuItemIds(@NonNull List menuItems) { + for (HashMap item : customToolbarItems) { + String customId = item.get("id").toString(); + int index = (Integer) item.get("index"); + int resId = getCustomResourceId(customId, "id", getContext()); + menuItems.add(Math.min(menuItems.size(), index), resId); + } + return menuItems; + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + + for (HashMap item : customToolbarItems) { + String customId = item.get("id").toString(); + String image = item.get("image").toString(); + String title = item.get("title") != null ? item.get("title").toString() : ""; + int resId = getCustomResourceId(customId, "id", getContext()); + Boolean showAsAction = item.get("showAsAction") != null ? (Boolean) item.get("showAsAction") : true; + MenuItem customMenuItem = menu.findItem(resId); + customMenuItem.setTitle(title); + int iconId = getCustomResourceId(image, "drawable", getContext()); + customMenuItem.setIcon(iconId); + customMenuItem.setShowAsAction(showAsAction == true ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER); + customMenuItem.setOnMenuItemClickListener(this.menuItemListener); + + // Apply toolbar theme color to custom menu item icon + Drawable customIcon = customMenuItem.getIcon(); + final TypedArray a = getContext().getTheme().obtainStyledAttributes( + null, + com.pspdfkit.R.styleable.pspdf__ActionBarIcons, + com.pspdfkit.R.attr.pspdf__actionBarIconsStyle, + com.pspdfkit.R.style.PSPDFKit_ActionBarIcons + ); + int mainToolbarIconsColor = a.getColor(com.pspdfkit.R.styleable.pspdf__ActionBarIcons_pspdf__iconsColor, ContextCompat.getColor(getContext(), android.R.color.white)); + a.recycle(); + try { + DrawableCompat.setTint(customIcon, mainToolbarIconsColor); + customMenuItem.setIcon(customIcon); + } catch (Exception e) { + // Omit the icon if the image is missing + } + } + } } diff --git a/android/src/main/res/drawable/pspdf__ic_navigation_arrow.xml b/android/src/main/res/drawable/pspdf__ic_navigation_arrow.xml index 9ccd340f..81e60e58 100644 --- a/android/src/main/res/drawable/pspdf__ic_navigation_arrow.xml +++ b/android/src/main/res/drawable/pspdf__ic_navigation_arrow.xml @@ -3,7 +3,7 @@ ~ ~ PSPDFKit ~ - ~ Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + ~ Copyright © 2021-2024 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. diff --git a/android/src/main/res/layout/pspdf__toolbar_main.xml b/android/src/main/res/layout/pspdf__toolbar_main.xml index 77564b3b..8d65333e 100644 --- a/android/src/main/res/layout/pspdf__toolbar_main.xml +++ b/android/src/main/res/layout/pspdf__toolbar_main.xml @@ -3,7 +3,7 @@ ~ ~ PSPDFKit ~ - ~ Copyright © 2014-2023 PSPDFKit GmbH. All rights reserved. + ~ Copyright © 2014-2024 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. diff --git a/android/src/main/res/values/attrs.xml b/android/src/main/res/values/attrs.xml index f96922e0..817747aa 100644 --- a/android/src/main/res/values/attrs.xml +++ b/android/src/main/res/values/attrs.xml @@ -4,7 +4,7 @@ ~ ~ PSPDFKit ~ - ~ Copyright © 2021-2023 PSPDFKit GmbH. All rights reserved. + ~ Copyright © 2021-2024 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. diff --git a/documentation/configuration-options.md b/documentation/configuration-options.md index 9bd82ff2..bce9501d 100644 --- a/documentation/configuration-options.md +++ b/documentation/configuration-options.md @@ -8,6 +8,7 @@ Here's the complete list of configuration options supported by each platform. No | ---------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `scrollDirection` | `String` | `horizontal`, `vertical` | ✅ | ✅ | Configures the direction of page scrolling in the document view. | | `pageTransition` | `String` | `scrollPerSpread`, `scrollContinuous`, `curl` | ✅ | ✅ | Configures the page scrolling mode. Note that curl mode is only available for iOS and will be ignored on Android. | +| `documentPassword` | `String` | | ✅ | ✅ | The password to unlock the document. | | `enableTextSelection` | `Boolean` | `true` / `false` | ✅ | ✅ | Allow / disallow text selection. | | `autosaveEnabled` | `Boolean` | `true` / `false` | ✅ | ✅ | Determines whether PSPDFKit should save automatically in response to [certain UI triggers][], such as the app entering the background or the view disappearing. | | `disableAutomaticSaving` | `Boolean` | `true` / `false` | ✅ | ✅ | Determines whether PSPDFKit should save automatically in response to [certain UI triggers][], such as the app entering the background or the view disappearing. | @@ -23,7 +24,7 @@ Here's the complete list of configuration options supported by each platform. No | `iOSMinimumZoomScale` | `float` | - | ✅ | ❌ | Minimum zoom scale for the scroll view. | | `iOSMaximumZoomScale` | `float` | - | ✅ | ❌ | Maximum zoom scale for the scroll view. | | `iOSDoubleTapAction` | `String` | `none`, `zoom`, `smartZoom` | ✅ | ❌ | The action that happens when the user double taps somewhere in the document. | -| `iOSTextSelectionMode` | `String` | `regular`, `simple` | ✅ | ❌ | Defines how the text is selected. | +| `iOSTextSelectionMode` | `String` | `regular`, `simple`, `automatic` | ✅ | ❌ | Defines how the text is selected. | | `iOSTypesShowingColorPresets` | `Set` | `none`, `undefined`, `all`, `Link`, `Highlight`, `Underline`, `Squiggly`, `StrikeOut`, `Text`, `Caret`, `FreeText`, `Ink`, `Square`, `Circle`, `Line`, `Signature`, `Stamp`, `Eraser`, `Image`, `Widget`, `FileAttachment`, `Sound`, `Polygon`, `PolyLine`, `RichMedia`, `Screen`, `Popup`, `Watermark`, `TrapNet`, `3D`, `Redact` | ✅ | ❌ | Shows a custom cell with configurable color presets for the provided annotation types. | #### Document Presentation Options @@ -78,6 +79,7 @@ Here's the complete list of configuration options supported by each platform. No | `iOSSettingsOptions` | `Set` | `scrollDirection`, `pageTransition`, `appearance`, `brightness`, `pageMode`, `spreadFitting`, `default`, `all` | ✅ | ❌ | Options that will be presented by `PDFSettingsViewController`. Defaults to `.default`. | | `iOSShadowEnabled` | `Boolean` | `true` / `false` | ✅ | ❌ | Enable / disable page shadow. | | `iOSShadowOpacity` | `float` | - | ✅ | ❌ | Set the default `shadowOpacity`. | +| `measurementValueConfigurations` | `MeasurementValueConfiguration`[] | - | ✅ | ✅ | The array of `MeasurementValueConfiguration` objects that should be applied to the document. | #### Thumbnail Options diff --git a/documentation/jsdoc.md b/documentation/jsdoc.md index 90eb97de..b4e01970 100644 --- a/documentation/jsdoc.md +++ b/documentation/jsdoc.md @@ -25,6 +25,6 @@ For Troubleshooting common issues you might encounter when setting up PSPDFKit f ## License This project can be used for evaluation or if you have a valid PSPDFKit license. -All items and source code Copyright © 2010-2023 PSPDFKit GmbH. +All items and source code Copyright © 2010-2024 PSPDFKit GmbH. See [LICENSE](https://github.com/PSPDFKit/react-native/blob/master/LICENSE) for details. diff --git a/index.js b/index.js index c4b31095..f11d1068 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. @@ -24,9 +24,9 @@ import { * ); } else { @@ -158,6 +159,15 @@ class PSPDFKitView extends React.Component { this._requestMap.delete(requestId); }; + /** + * @ignore + */ + _onCustomToolbarButtonTapped = event => { + if (this.props.onCustomToolbarButtonTapped) { + this.props.onCustomToolbarButtonTapped(event.nativeEvent); + } + }; + /** * Enters annotation creation mode, showing the annotation creation toolbar. * @method enterAnnotationCreationMode @@ -683,31 +693,88 @@ class PSPDFKitView extends React.Component { }; /** - * @typedef MeasurementConfig - * @property { string } unitFrom The unit for the distance on a document page. - * @property { number } valueFrom A distance on a document page. - * @property { string } unitTo The unit for the real-world distance. - * @property { number } valueTo A real-world distance. - * @property { string } precision This value is used as the default measurement precision when creating new measurement annotations. Available options are: ```whole```, ```oneDP```, ```twoDP```, ```threeDP```, and ```fourDP```. + * Sets the Toolbar object to customize the toolbar appearance and behaviour. + * + * @method setToolbar + * @memberof PSPDFKitView + * @param { Toolbar } toolbar The toolbar object. + * @example + * const toolbar = { + * // iOS + * rightBarButtonItems: { + * viewMode: Toolbar.PDFViewMode.VIEW_MODE_DOCUMENT, + * animated: true, + * buttons: ['searchButtonItem', 'readerViewButtonItem'] + * }, + * // Android + * toolbarMenuItems: { + * buttons: ['searchButtonItem', 'readerViewButtonItem'] + * }, + * } + * this.refs.pdfView.setToolbar(toolbar); + * + */ + setToolbar = function (toolbar) { + if (Platform.OS === 'ios') { + NativeModules.PSPDFKitViewManager.setToolbar( + toolbar, + findNodeHandle(this.refs.pdfView), + ); + } else if (Platform.OS === 'android') { + UIManager.dispatchViewManagerCommand( + findNodeHandle(this.refs.pdfView), + this._getViewManagerConfig('RCTPSPDFKitView').Commands + .setToolbar, + [toolbar], + ); + } + }; + + /** + * Gets the toolbar for the specified view mode. + * + * @method getToolbar + * @memberof PSPDFKitView + * @param { string } [viewMode] The view mode to query. Options are: ```document```, ```thumbnails```, ```documentEditor```, or ```null```. If ```null``` is passed, the toolbar buttons for the current view mode are returned. + * + * @returns { Promise> } A promise containing the toolbar object, or an error if it couldn’t be retrieved. + * @example + * const toolbar = await this.pdfRef.current.getToolbar('document'); + * */ + getToolbar = function (viewMode) { + if (Platform.OS === 'ios') { + return NativeModules.PSPDFKitViewManager.getToolbar( + viewMode, + findNodeHandle(this.refs.pdfView), + ); + } + }; /** - * Sets the measurements configuration for the ```PSPDFKitView```. + * Sets the measurement value configurations for the ```PSPDFKitView```. * - * @method setMeasurementConfig + * @method setMeasurementValueConfigurations * @memberof PSPDFKitView - * @param { MeasurementConfig } config The measurement configuration object. + * @param { MeasurementValueConfiguration[] } configurations The array of MeasurementValueConfiguration objects that should be applied to the document. * @example - * const config = { - * unitForm: "inch", - * valueFrom: 2.74, - * unitTo: "mm", - * valueTo: 69.60 - * precision: 'twodp' - * }; - * const result = await this.pdfRef.current.setMeasurementConfig(config); + * const scale: MeasurementScale = { + * unitFrom: Measurements.ScaleUnitFrom.INCH, + * valueFrom: 1.0, + * unitTo: Measurements.ScaleUnitTo.INCH, + * valueTo: 2.54 + * }; + * + * const measurementValueConfig: MeasurementValueConfiguration = { + * name: 'Custom Scale', + * scale: scale, + * precision: Measurements.Precision.FOUR_DP + * }; + * + * const configs = [measurementValueConfig]; + * await this.pdfRef.current?.setMeasurementValueConfigurations(configs); */ - setMeasurementConfig = function (config) { + setMeasurementValueConfigurations = function (configurations) { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; @@ -721,43 +788,30 @@ class PSPDFKitView extends React.Component { findNodeHandle(this.refs.pdfView), this._getViewManagerConfig( 'RCTPSPDFKitView', - ).Commands.setMeasurementConfig(config), - [requestId, config], + ).Commands.setMeasurementValueConfigurations, + [requestId, configurations], ); return promise; } - NativeModules.PSPDFKitViewManager.setMeasurementConfig( - config, + NativeModules.PSPDFKitViewManager.setMeasurementValueConfigurations( + configurations, findNodeHandle(this.refs.pdfView), ); }; /** - * @typedef MeasurementScale - * @property { string } unitFrom The unit for the distance on a document page. - * @property { number } valueFrom A distance on a document page. - * @property { string } unitTo The unit for the real-world distance. - * @property { number } valueTo A real-world distance. - */ - - /** - * Sets the measurements scale for the ```PSPDFKitView```. + * Gets the current PSPDFKitView MeasurementValueConfigurations. * - * @method setMeasurementScale + * @method getMeasurementValueConfigurations * @memberof PSPDFKitView - * @param { MeasurementScale } scale The scale object. + * + * @returns { Promise } A promise containing an array of ```MeasurementValueConfiguration``` objects. * @example - * const config = { - * unitForm: "inch", - * valueFrom: 2.74, - * unitTo: "mm", - * valueTo: 69.60 - * }; - * const result = await this.pdfRef.current.setMeasurementScale(config); + * const configurations = await this.pdfRef.current.getMeasurementValueConfigurations(); */ - setMeasurementScale = function (scale) { + getMeasurementValueConfigurations = function () { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; @@ -770,30 +824,52 @@ class PSPDFKitView extends React.Component { UIManager.dispatchViewManagerCommand( findNodeHandle(this.refs.pdfView), this._getViewManagerConfig('RCTPSPDFKitView').Commands - .setMeasurementScale, - [requestId, scale], + .getMeasurementValueConfigurations, + [requestId], ); return promise; } - - // iOS implementation - NativeModules.PSPDFKitViewManager.setMeasurementScale( - scale, - findNodeHandle(this.refs.pdfView), - ); + else if (Platform.OS === 'ios') { + return NativeModules.PSPDFKitViewManager.getMeasurementValueConfigurations( + findNodeHandle(this.refs.pdfView), + ); + } + }; + + /** + * Customizes the visible toolbar menu items for Android. + * + * @method setToolbarMenuItems + * @memberof PSPDFKitView + * @param { Array } toolbarMenuItems The list of bar button items. + * @see {@link https://pspdfkit.com/guides/react-native/user-interface/toolbars/main-toolbar/} for supported button items. + * @example + * const result = await this.pdfRef.current.setToolbarMenuItems(['searchButtonItem', 'readerViewButtonItem']); + * + */ + setToolbarMenuItems = function (toolbarMenuItems) { + if (Platform.OS === 'android') { + UIManager.dispatchViewManagerCommand( + findNodeHandle(this.refs.pdfView), + this._getViewManagerConfig('RCTPSPDFKitView').Commands + .setToolbarMenuItems, + [toolbarMenuItems], + ); + } }; /** - * Sets the measurements precision for the ```PSPDFKitView```. + * Gets the current PSPDFKitView configuration. * - * @method setMeasurementPrecision + * @method getConfiguration * @memberof PSPDFKitView - * @param { string } precision This value is used as the default measurement precision when creating new measurement annotations. Available options are: ```whole```, ```oneDP```, ```twoDP```, ```threeDP```, and ```fourDP```. + * + * @returns { Promise } A promise containing a ```PDFConfiguration``` object with the document configuration. * @example - * const result = await this.pdfRef.current.setMeasurementPrecision('fourDP'); + * const configuration = await this.pdfRef.current.getConfiguration(); */ - setMeasurementPrecision = function (precision) { + getConfiguration = function () { if (Platform.OS === 'android') { let requestId = this._nextRequestId++; let requestMap = this._requestMap; @@ -806,37 +882,15 @@ class PSPDFKitView extends React.Component { UIManager.dispatchViewManagerCommand( findNodeHandle(this.refs.pdfView), this._getViewManagerConfig('RCTPSPDFKitView').Commands - .setMeasurementPrecision, - [requestId, precision], + .getConfiguration, + [requestId], ); return promise; } - // iOS implementation - NativeModules.PSPDFKitViewManager.setMeasurementPrecision( - precision, - findNodeHandle(this.refs.pdfView), - ); - }; - - /** - * Customizes the visible toolbar menu items for Android. - * - * @method setToolbarMenuItems - * @memberof PSPDFKitView - * @param { Array } toolbarMenuItems The list of bar button items. - * @see {@link https://pspdfkit.com/guides/react-native/user-interface/toolbars/main-toolbar/} for supported button items. - * @example - * const result = await this.pdfRef.current.setToolbarMenuItems(['searchButtonItem', 'readerViewButtonItem']); - * - */ - setToolbarMenuItems = function (toolbarMenuItems) { - if (Platform.OS === 'android') { - UIManager.dispatchViewManagerCommand( + else if (Platform.OS === 'ios') { + return NativeModules.PSPDFKitViewManager.getConfiguration( findNodeHandle(this.refs.pdfView), - this._getViewManagerConfig('RCTPSPDFKitView').Commands - .setToolbarMenuItems, - [toolbarMenuItems], ); } }; @@ -895,7 +949,8 @@ if (Platform.OS === 'ios' || Platform.OS === 'android') { * @ignore * @typedef {object} Props * @property {string} document The path to the PDF file that should be displayed. - * @property {object} [configuration] Configuration object to customize the appearance and behavior of PSPDFKit. See {@link https://github.com/PSPDFKit/react-native/blob/master/documentation/configuration-options.md} for available options. + * @property {PDFConfiguration} [configuration] Configuration object to customize the appearance and behavior of PSPDFKit. See {@link https://pspdfkit.com/api/react-native/PDFConfiguration.html} for available options. + * @property {Toolbar} [toolbar] Toolbar object to customize the toolbar appearance and behaviour. * @property {number} [pageIndex] Page index of the document that will be shown. Starts at 0. * @property {boolean} [hideNavigationBar] Controls whether a navigation bar is created and shown or not. Navigation bar is shown by default (```false```). * @property {boolean} [showCloseButton] Specifies whether the close button should be shown in the navigation bar. Disabled by default (```false```). Only applies when the ```PSPDFKitView``` is presented modally. Will call ```onCloseButtonPressed``` when tapped if a callback was provided. If ```onCloseButtonPressed``` wasn’t provided, ```PSPDFKitView``` will automatically be dismissed when modally presented. @@ -909,6 +964,7 @@ if (Platform.OS === 'ios' || Platform.OS === 'android') { * @property {function} [onAnnotationTapped] Callback that’s called when an annotation is tapped. * @property {function} [onAnnotationsChanged] Callback that’s called when an annotation is added, changed, or removed. * @property {function} [onStateChanged] Callback that’s called when the state of the ```PSPDFKitView``` changes. + * @property {function} [onCustomToolbarButtonTapped] Callback that’s called when a custom toolbar button is tapped. * @property {string} [fragmentTag] The tag used to identify a single PdfFragment in the view hierarchy. This needs to be unique in the view hierarchy. * @property {Array} [menuItemGrouping] Used to specify a custom grouping for the menu items in the annotation creation toolbar. * @property {Array} [leftBarButtonItems] Sets the left bar button items. Note: The same button item cannot be added to both the left and right bar button items simultaneously. See {@link https://github.com/PSPDFKit/react-native/blob/master/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.m} for supported button items. @@ -917,9 +973,9 @@ if (Platform.OS === 'ios' || Platform.OS === 'android') { * @property {Array} [toolbarMenuItems] Used to customize the toolbar menu items for Android. See {@link https://github.com/PSPDFKit/react-native/blob/master/android/src/main/java/com/pspdfkit/react/ToolbarMenuItemsAdapter.java} for supported toolbar menu items. * @property {boolean} [showNavigationButtonInToolbar] When set to ```true```, the toolbar integrated into the ```PSPDFKitView``` will display a back button in the top-left corner. * @property {function} [onNavigationButtonClicked] If ```showNavigationButtonInToolbar``` is set to ```true```, this callback will notify you when the back button is tapped. - * @property {Array} [availableFontNames] Used to specify the available font names in the font picker. Note on iOS: You need to set the desired font family names as ```UIFontDescriptor```. See {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. See {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.js} - * @property {string} [selectedFontName] Used to specify the current selected font in the font picker. Note on iOS: You need to set the desired font family names as ```UIFontDescriptor```. See {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. See {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.js} - * @property {boolean} [showDownloadableFonts] Used to show or hide the downloadable fonts section in the font picker. Defaults to ```true```, showing the downloadable fonts. See {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. See {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.js} + * @property {Array} [availableFontNames] Used to specify the available font names in the font picker. Note on iOS: You need to set the desired font family names as ```UIFontDescriptor```. See {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. See {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.tsx} + * @property {string} [selectedFontName] Used to specify the current selected font in the font picker. Note on iOS: You need to set the desired font family names as ```UIFontDescriptor```. See {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. See {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.tsx} + * @property {boolean} [showDownloadableFonts] Used to show or hide the downloadable fonts section in the font picker. Defaults to ```true```, showing the downloadable fonts. See {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. See {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.tsx} * @property {object} [annotationPresets] The annotation preset configuration. See {@link https://github.com/PSPDFKit/react-native/blob/5b2716a3f3cd3732c0e5845cc39e28d19b618aa4/ios/RCTPSPDFKit/Converters/AnnotationConfigurationsConvertor.swift#L31} for a list of the supported preset types and {@link https://github.com/PSPDFKit/react-native/blob/5b2716a3f3cd3732c0e5845cc39e28d19b618aa4/ios/RCTPSPDFKit/Converters/AnnotationConfigurationsConvertor.swift#L13} for the supported configuration options. * @property {boolean} [hideDefaultToolbar] Used to show or hide the annotation toolbar on Android. * @property {any} [style] Used to style the React Native component. @@ -936,13 +992,19 @@ PSPDFKitView.propTypes = { document: PropTypes.string.isRequired, /** * Configuration object to customize the appearance and behavior of PSPDFKit. - * @type {object} + * @type {PDFConfiguration} * @memberof PSPDFKitView - * @see {@link https://github.com/PSPDFKit/react-native/blob/master/documentation/configuration-options.md} for available options. + * @see {@link https://pspdfkit.com/api/react-native/PDFConfiguration.html} for available options. * Note: On iOS, set the ```useParentNavigationBar``` configuration option to ```true``` if you're using a navigation plugin such as * ```NavigatorIOS``` or ```react-native-navigation```. This is because the plugin will manage the navigation bar. */ configuration: PropTypes.object, + /** + * Toolbar object to customize the toolbar appearance and behaviour. + * @type {Toolbar} + * @memberof PSPDFKitView + */ + toolbar: PropTypes.object, /** * Page index of the document that will be shown. Starts at 0. * @type {number} @@ -1081,6 +1143,20 @@ PSPDFKitView.propTypes = { * }} */ onStateChanged: PropTypes.func, + /** + * Callback that’s called when a custom toolbar button is tapped. + * @type {function} + * @memberof PSPDFKitView + * @example + * onCustomToolbarButtonTapped={result => { + * if (result.error) { + * alert(result.error); + * } else { + * alert('Custom bar button item tapped: ' + JSON.stringify(result)); + * } + * }} + */ + onCustomToolbarButtonTapped: PropTypes.func, /** * The tag used to identify a single ```PdfFragment``` in the view hierarchy. * This needs to be unique in the view hierarchy. @@ -1150,7 +1226,7 @@ PSPDFKitView.propTypes = { * @type {Array} * @memberof PSPDFKitView * @see {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. - * @see {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.js} + * @see {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.tsx} */ availableFontNames: PropTypes.array, /** @@ -1159,7 +1235,7 @@ PSPDFKitView.propTypes = { * @type {string} * @memberof PSPDFKitView * @see {@link https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc} for more information. - * @see {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.js} + * @see {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.tsx} * * Note on Android: This is the default font that’s selected. If the user changes the font, it’ll become the new default. */ @@ -1169,7 +1245,7 @@ PSPDFKitView.propTypes = { * Defaults to ```true```, showing the downloadable fonts. * @type {boolean} * @memberof PSPDFKitView - * @see {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.js} + * @see {@link https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/examples/CustomFontPicker.tsx} */ showDownloadableFonts: PropTypes.bool, /** @@ -1235,7 +1311,7 @@ export class PSPDFKit { * Used to get the current version of the underlying PSPDFKit SDK. * @member versionString * @memberof PSPDFKit - * @returns { string } The underlying PSPDFKit SDK version number. + * @type { string } * @example * const version = PSPDFKit.versionString */ @@ -1273,7 +1349,7 @@ export class PSPDFKit { * @method present * @memberof PSPDFKit * @param { string } documentPath The path to the PDF document to be presented. - * @param { object } configuration Configuration object to customize the appearance and behavior of PSPDFKit. See {@link https://github.com/PSPDFKit/react-native/blob/master/documentation/configuration-options.md} for available options. + * @param { PDFConfiguration } configuration Configuration object to customize the appearance and behavior of PSPDFKit. See {@link https://pspdfkit.com/api/react-native/PDFConfiguration.html} for available options. * @returns { Promise } A promise returning ```true``` if the document was successfully presented, and ```false``` if not. * @example * const fileName = 'document.pdf'; @@ -1281,10 +1357,11 @@ export class PSPDFKit { * Platform.OS === 'ios' ? 'PDFs/' + fileName * : 'file:///android_asset/' + fileName; * - * const configuration = { - * showThumbnailBar: 'scrollable', - * pageTransition: 'scrollContinuous', - * scrollDirection: 'vertical' + * const configuration: PDFConfiguration = { + * pageMode: PDFConfiguration.PageMode.AUTOMATIC, + * scrollDirection: PDFConfiguration.ScrollDirection.HORIZONTAL, + * enableAnnotationEditing: PDFConfiguration.BooleanType.TRUE, + * pageTransition: PDFConfiguration.PageTransition.SCROLL_CONTINUOUS * }; * * PSPDFKit.present(exampleDocumentPath, configuration); @@ -1341,7 +1418,7 @@ export class PSPDFKit { * @method presentInstant * @memberof PSPDFKit * @param { InstantDocumentData } documentData The Instant document data received entirely from the web response. - * @param { object } configuration Configuration object to customize the appearance and behavior of PSPDFKit. See {@link https://github.com/PSPDFKit/react-native/blob/master/documentation/configuration-options.md} for available options. Also see {@link InstantConfiguration} for additional Instant configuration options. + * @param { PDFConfiguration } configuration Configuration object to customize the appearance and behavior of PSPDFKit. See {@link https://pspdfkit.com/api/react-native/PDFConfiguration.html} for available options. Also see {@link InstantConfiguration} for additional Instant configuration options. * @returns { Promise } A promise returning ```true``` if the document was successfully presented, and ```false``` if not. * @see {@link https://github.com/PSPDFKit/react-native/blob/5b2716a3f3cd3732c0e5845cc39e28d19b618aa4/samples/Catalog/examples/InstantSynchronization.js#L85C7-L85C7} for an example implementation. * @example @@ -1351,11 +1428,11 @@ export class PSPDFKit { * jwt: serverResult.jwt, * serverUrl: Constants.InstantServerURL * }; - * const configuration = { - * enableInstantComments: false, - * listenToServerChanges: true, + * const configuration: PDFConfiguration = { + * enableInstantComments: PDFConfiguration.BooleanType.FALSE, + * listenToServerChanges: PDFConfiguration.BooleanType.TRUE, * delay: 1, - * syncAnnotations: true, + * syncAnnotations: PDFConfiguration.BooleanType.TRUE, * }; * * PSPDFKit.presentInstant(documentData, configuration); @@ -1644,3 +1721,24 @@ export class Processor { */ getTemporaryDirectory = function () {}; } + +import { PDFConfiguration } from "./lib/configuration/PDFConfiguration"; +export { PDFConfiguration } from "./lib/configuration/PDFConfiguration"; + +import { Toolbar } from "./lib/toolbar/Toolbar"; +export { Toolbar } from "./lib/toolbar/Toolbar"; + +import { Measurements } from "./lib/measurements/Measurements"; +export { Measurements } from "./lib/measurements/Measurements"; + +import { MeasurementScale } from "./lib/measurements/Measurements"; +export { MeasurementScale } from "./lib/measurements/Measurements"; + +import { MeasurementValueConfiguration } from "./lib/measurements/Measurements"; +export { MeasurementValueConfiguration } from "./lib/measurements/Measurements"; + +module.exports.PDFConfiguration = PDFConfiguration; +module.exports.Toolbar = Toolbar; +module.exports.Measurements = Measurements; +module.exports.MeasurementScale = MeasurementScale; +module.exports.MeasurementValueConfiguration = MeasurementValueConfiguration; diff --git a/ios/RCTPSPDFKit/Converters/AnnotationConfigurationsConvertor.swift b/ios/RCTPSPDFKit/Converters/AnnotationConfigurationsConvertor.swift index 070fdba1..c642a88d 100644 --- a/ios/RCTPSPDFKit/Converters/AnnotationConfigurationsConvertor.swift +++ b/ios/RCTPSPDFKit/Converters/AnnotationConfigurationsConvertor.swift @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/PspdfkitMeasurementConvertor.swift b/ios/RCTPSPDFKit/Converters/PspdfkitMeasurementConvertor.swift index 38a41a98..60a58edd 100644 --- a/ios/RCTPSPDFKit/Converters/PspdfkitMeasurementConvertor.swift +++ b/ios/RCTPSPDFKit/Converters/PspdfkitMeasurementConvertor.swift @@ -1,5 +1,5 @@ // -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. @@ -7,114 +7,222 @@ // This notice may not be removed from this file. // -import Foundation - import Foundation import PSPDFKit import PSPDFKitUI @objc(PspdfkitMeasurementConvertor) -public class PspdfkitMeasurementConvertor: NSObject { +public class PspdfkitMeasurementConvertor :NSObject{ + /** - * Converts precision string from React Native layer to MeasurementPrecision enum - * - * @param precision The string representation of a measurement precision. - * @return The MeasurementPrecision enum. - */ - @objc public static func getPrecision(_ precision: String?) -> MeasurementPrecision { - let precisionOptions: [String: MeasurementPrecision] = [ - "whole": .whole, - "onedp": .oneDecimalPlace, - "twodp": .twoDecimalPlaces, - "threedp": .threeDecimalPlaces, - "fourdp": .fourDecimalPlaces, - ] - - guard - let precision = precision?.lowercased(), - let precisionValue = precisionOptions[precision] - else { - return .twoDecimalPlaces + * Add a new measurement configuration to the document. + * @param document The document to which the measurement configuration should be added. + * @param configuration The measurement configuration to be added. + */ + @objc static public func addMeasurementValueConfiguration(document: Document, configuration:NSDictionary) -> Bool { + guard let measurementValueConfiguration = convertMeasurementValueConfiguration(measurementValueConfiguration: configuration) else { + return false; } - - return precisionValue + document.add(measurementValueConfiguration: measurementValueConfiguration) + if let isSelected = configuration.object(forKey: "isSelected") as? Bool, isSelected == true { + document.activeMeasurementValueConfiguration = measurementValueConfiguration; + } + return true } - @objc public static func getPrecisionInt(_ precision: String?) -> Int { - return self.getPrecision(precision).rawValue + /** + * Remove a measurement configuration from the document. + * @param document The document from which the measurement configuration should be removed. + * @param name The name of the measurement configuration to be removed. + */ + @objc static public func removeMeasurementValueConfiguration(document: Document, name: NSString) { + // TODO: Implement remove measurementValue configuration. This is not yet implemented in the PSPDFKit iOS SDK. } - @objc public static func getScaleConfig(_ rawData: [String: AnyObject]) -> MeasurementScale? { - var fromValue: Double = 1 - var toValue: Double = 1 - var unitFrom: UnitFrom = .inch - var unitTo: UnitTo = .inch - - for (key, value) in rawData { - switch key.lowercased() { - case "unitfrom": - unitFrom = parseScaleUnitFrom(value as? String ?? "") - case "unitto": - unitTo = parseScaleUnitTo(value as? String ?? "") - case "fromvalue": - fromValue = value as? Double ?? 1 - case "tovalue": - toValue = value as? Double ?? 1 - - default: - break - } + /** + * Get all measurement configurations from the document. + * @param document The document from which the measurement configurations should be retrieved. + * @return An array of measurement configurations. + */ + @objc static public func getMeasurementValueConfigurations(document: Document) -> NSArray { + let configurations = document.measurementValueConfigurations + var result = [NSDictionary]() + for configuration in configurations { + result.append(reverserMeasurementValueConfiguration(configuration: configuration) as NSDictionary) } + return result as NSArray + } - let config = MeasurementScale(from: fromValue, unitFrom: unitFrom, to: toValue, unitTo: unitTo) - return config + /** + * Modify a measurement configuration in the document. + * @param document The document in which the measurement configuration should be modified. + * @param configuration The measurement configuration to be modified. + */ + @objc static public func modifyMeasurementValueConfiguration(document: Document, configuration:NSDictionary) { + // TODO: Implement modify measurementValue configuration. This is not yet implemented in the PSPDFKit iOS SDK. + } + + static private func convertMeasurementValueConfiguration(measurementValueConfiguration: NSDictionary) -> MeasurementValueConfiguration? { + if (measurementValueConfiguration == NSNull()){ + return nil + } + guard let measurement = measurementValueConfiguration["scale"] as? NSDictionary else { + return nil; + } + + guard let scale = convertScale(measurement: measurement) else { + return nil; + } + let precision = convertPrecision(precision: measurementValueConfiguration["precision"] as? NSString) + let name = measurementValueConfiguration["name"] as? String + return MeasurementValueConfiguration(name: name, scale: scale, precision: precision) + } + + static private func reverserMeasurementValueConfiguration(configuration: MeasurementValueConfiguration) -> NSDictionary { + let scale = reverseConvertScale(scale: configuration.scale) + let precision = reverseConvertPrecision(precision: configuration.precision) + return ["scale": scale, "precision": precision, "name": configuration.name ?? ""] } - @objc public static func parseScaleUnitTo(_ stringValue: String) -> UnitTo { - let options: [String: UnitTo] = [ - "inch": .inch, - "mm": .millimeter, - "cm": .centimeter, - "pt": .point, - "ft": .foot, - "m": .meter, - "yd": .yard, - "km": .kilometer, - "mi": .mile, - ]; + static private func convertScale(measurement: NSDictionary) -> MeasurementScale? { + if (measurement == NSNull()) { + return nil + } + + guard let valueFrom = measurement["valueFrom"] as? Double else { return nil } + guard let valueTo = measurement["valueTo"] as? Double else { return nil } + let unitFrom = measurement["unitFrom"] as? NSString + let unitTo = measurement["unitTo"] as? NSString + let fromUnits: UnitFrom = convertUnitFrom(unit: unitFrom) + let toUnits: UnitTo = convertUnitTo(unit: unitTo) - guard let unitTo = options[stringValue.lowercased()] else { + return MeasurementScale(from: valueFrom, unitFrom: fromUnits, to: valueTo, unitTo: toUnits) + } + + + static private func convertUnitFrom(unit: NSString?) -> UnitFrom { + if(unit == NSNull()){ + return .centimeter + } + switch unit { + case "inch": return .inch + case "cm": + return .centimeter + case "mm": + return .millimeter + case "pt": + return .point + default: + return .centimeter } - - return unitTo } - @objc public static func parseScaleUnitFrom(_ stringValue: String) -> UnitFrom { - let options: [String: UnitFrom] = [ - "inch": .inch, - "mm": .millimeter, - "cm": .centimeter, - "pt": .point - ]; - - guard let unitFrom = options[stringValue.lowercased()] else { + static private func convertUnitTo(unit: NSString?) -> UnitTo { + if(unit == NSNull()){ + return .centimeter + } + switch unit { + case "inch": return .inch + case "cm": + return .centimeter + case "mm": + return .millimeter + case "m": + return .meter + case "km": + return .kilometer + case "yd": + return .yard + case "ft": + return .foot + case "mi": + return .mile + default: + return .centimeter } + } + + + static private func convertPrecision(precision: NSString?) -> MeasurementPrecision { + if(precision == NSNull()){ + return .twoDecimalPlaces + } + switch precision { + case "oneDP": + return .oneDecimalPlace + case "twoDP": + return .twoDecimalPlaces + case "threeDP": + return .threeDecimalPlaces + case "fourDP": + return .fourDecimalPlaces + case "whole": + return .whole + default: + return .twoDecimalPlaces + } + } - return unitFrom + static private func reverseConvertScale(scale: MeasurementScale) -> NSDictionary { + let fromUnit = reverseUnitFrom(unit: scale.unitFrom) + let toUnit = reverseUnitsTo(unit: scale.unitTo) + return ["valueFrom": scale.from, "valueTo": scale.to, "unitFrom": fromUnit, "unitTo": toUnit] } - @objc public static func setConfig(_ configuration: [String: AnyObject], document: Document?) { - if - let scaleData = configuration["measurementScale"] as? [String: AnyObject], - let scale = self.getScaleConfig(scaleData) { - document?.measurementScale = scale + static private func reverseUnitFrom(unit: UnitFrom) -> String { + switch unit { + case .inch: + return "inch" + case .centimeter: + return "cm" + case .millimeter: + return "mm" + default: + return "cm" + } + } + + static private func reverseUnitsTo(unit: UnitTo) -> String { + switch unit { + case .inch: + return "inch" + case .centimeter: + return "cm" + case .millimeter: + return "mm" + case .point: + return "pt" + case .meter: + return "m" + case .kilometer: + return "km" + case .yard: + return "yd" + case .foot: + return "ft" + case .mile: + return "mi" + default: + return "" } + } - if - let precision = configuration["measurementPrecision"] as? String { - document?.measurementPrecision = self.getPrecision(precision) + static private func reverseConvertPrecision(precision: MeasurementPrecision) -> String { + switch precision { + case .oneDecimalPlace: + return "oneDP" + case .twoDecimalPlaces: + return "twoDP" + case .threeDecimalPlaces: + return "threeDP" + case .fourDecimalPlaces: + return "fourDP" + case .whole: + return "whole" + default: + return "twoDP" } } } diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h index b08928ee..5c9c0a70 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m index 7fea81ff..742446a5 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.h b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.h index f4a1f9d9..35dcd525 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.h @@ -1,5 +1,5 @@ // -// Copyright © 2019-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2019-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.m b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.m index a9c4a3a2..939055be 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.m @@ -1,5 +1,5 @@ // -// Copyright © 2019-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2019-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.h b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.h index 82268421..5519729b 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.h @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.m b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.m index 048b8ecf..17227f58 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.m @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.h b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.h index 42276192..3b47cd8d 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.h @@ -1,5 +1,5 @@ // -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2016-2024 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. @@ -27,6 +27,8 @@ // - `iOS` prefix : If the key works only for iOS. + (NSDictionary *)processConfigurationOptionsDictionaryForPrefix:(NSDictionary *)dictionary; ++ (NSDictionary *)convertConfiguration:(PSPDFViewController *)viewController; + @end @interface PSPDFConfigurationBuilder (RNAdditions) diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.m b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.m index 6c6ac4d2..accbe1a2 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.m @@ -1,5 +1,5 @@ // -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2016-2024 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. @@ -14,6 +14,124 @@ #import #endif +#define PageTransitionMap @{@"scrollPerSpread" : @(PSPDFPageTransitionScrollPerSpread), \ + @"scrollContinuous" : @(PSPDFPageTransitionScrollContinuous), \ + @"curl" : @(PSPDFPageTransitionCurl)} \ + +#define PageModeMap @{@"single" : @(PSPDFPageModeSingle), \ + @"double" : @(PSPDFPageModeDouble), \ + @"automatic" : @(PSPDFPageModeAutomatic)} \ + +#define ScrollDirectionMap @{@"horizontal" : @(PSPDFScrollDirectionHorizontal), \ + @"vertical" : @(PSPDFScrollDirectionVertical)} \ + +#define AppearanceModeMap @{@"default" : @(PSPDFAppearanceModeDefault), \ + @"sepia" : @(PSPDFAppearanceModeSepia), \ + @"night" : @(PSPDFAppearanceModeNight), \ + @"all" : @(PSPDFAppearanceModeAll)} \ + +#define SpreadFittingMap @{@"fit" : @(PSPDFConfigurationSpreadFittingFit), \ + @"fill" : @(PSPDFConfigurationSpreadFittingFill), \ + @"adaptive" : @(PSPDFConfigurationSpreadFittingAdaptive)} \ + +#define SignatureSavingStrategyMap @{@"alwaysSave" : @(PSPDFSignatureSavingStrategyAlwaysSave), \ + @"neverSave" : @(PSPDFSignatureSavingStrategyNeverSave), \ + @"saveIfSelected" : @(PSPDFSignatureSavingStrategySaveIfSelected)} \ + +#define DoubleTapActionMap @{@"none" : @(PSPDFTapActionNone), \ + @"zoom" : @(PSPDFTapActionZoom), \ + @"smartZoom" : @(PSPDFTapActionSmartZoom)} \ + +#define TextSelectionModeMap @{@"regular" : @(PSPDFTextSelectionModeRegular), \ + @"simple" : @(PSPDFTextSelectionModeSimple), \ + @"automatic": @(PSPDFTextSelectionModeAutomatic)} \ + +#define TypesShowingColorPresetsMap @{@"none" : @(PSPDFAnnotationTypeNone), \ + @"undefined" : @(PSPDFAnnotationTypeUndefined), \ + PSPDFAnnotationStringLink : @(PSPDFAnnotationTypeLink), \ + PSPDFAnnotationStringHighlight : @(PSPDFAnnotationTypeHighlight), \ + PSPDFAnnotationStringStrikeOut : @(PSPDFAnnotationTypeStrikeOut), \ + PSPDFAnnotationStringUnderline : @(PSPDFAnnotationTypeUnderline), \ + PSPDFAnnotationStringSquiggly : @(PSPDFAnnotationTypeSquiggly), \ + PSPDFAnnotationStringFreeText : @(PSPDFAnnotationTypeFreeText), \ + PSPDFAnnotationStringInk : @(PSPDFAnnotationTypeInk), \ + PSPDFAnnotationStringSquare : @(PSPDFAnnotationTypeSquare), \ + PSPDFAnnotationStringCircle : @(PSPDFAnnotationTypeCircle), \ + PSPDFAnnotationStringLine : @(PSPDFAnnotationTypeLine), \ + PSPDFAnnotationStringNote : @(PSPDFAnnotationTypeNote), \ + PSPDFAnnotationStringStamp : @(PSPDFAnnotationTypeStamp), \ + PSPDFAnnotationStringCaret : @(PSPDFAnnotationTypeCaret), \ + PSPDFAnnotationStringRichMedia : @(PSPDFAnnotationTypeRichMedia), \ + PSPDFAnnotationStringScreen : @(PSPDFAnnotationTypeScreen), \ + PSPDFAnnotationStringWidget : @(PSPDFAnnotationTypeWidget), \ + PSPDFAnnotationStringFile : @(PSPDFAnnotationTypeFile), \ + PSPDFAnnotationStringSound : @(PSPDFAnnotationTypeSound), \ + PSPDFAnnotationStringPolygon : @(PSPDFAnnotationTypePolygon), \ + PSPDFAnnotationStringPolyLine : @(PSPDFAnnotationTypePolyLine), \ + PSPDFAnnotationStringPopup : @(PSPDFAnnotationTypePopup), \ + PSPDFAnnotationStringWatermark : @(PSPDFAnnotationTypeWatermark), \ + PSPDFAnnotationStringTrapNet : @(PSPDFAnnotationTypeTrapNet), \ + PSPDFAnnotationString3D : @(PSPDFAnnotationTypeThreeDimensional), \ + PSPDFAnnotationStringRedaction : @(PSPDFAnnotationTypeRedaction), \ + @"all" : @(PSPDFAnnotationTypeAll)} \ + +#define RenderStatusViewPositionMap @{@"top" : @(PSPDFRenderStatusViewPositionTop), \ + @"centered" : @(PSPDFRenderStatusViewPositionCentered)} \ + +#define UserInterfaceViewModeMap @{@"automatic" : @(PSPDFUserInterfaceViewModeAutomatic), \ + @"automaticBorderPages" : @(PSPDFUserInterfaceViewModeAutomaticNoFirstLastPage), \ + @"automaticNoFirstLastPage" : @(PSPDFUserInterfaceViewModeAutomaticNoFirstLastPage), \ + @"always" : @(PSPDFUserInterfaceViewModeAlways), \ + @"alwaysVisible" : @(PSPDFUserInterfaceViewModeAlways), \ + @"alwaysHidden" : @(PSPDFUserInterfaceViewModeNever), \ + @"never" : @(PSPDFUserInterfaceViewModeNever)} \ + +#define SearchModeMap @{@"modal" : @(PSPDFSearchModeModal), \ + @"inline" : @(PSPDFSearchModeInline)} \ + +#define AllowedMenuActionsMap @{@"none" : @(PSPDFTextSelectionMenuActionNone), \ + @"search" : @(PSPDFTextSelectionMenuActionSearch), \ + @"define" : @(PSPDFTextSelectionMenuActionDefine), \ + @"wikipedia" : @(PSPDFTextSelectionMenuActionWikipedia), \ + @"speak" : @(PSPDFTextSelectionMenuActionSpeak), \ + @"all" : @(PSPDFTextSelectionMenuActionAll)} \ + +#define SettingsOptionsMap @{@"scrollDirection" : @(PSPDFSettingsOptionScrollDirection), \ + @"pageTransition" : @(PSPDFSettingsOptionPageTransition), \ + @"appearance" : @(PSPDFSettingsOptionAppearance), \ + @"brightness" : @(PSPDFSettingsOptionBrightness), \ + @"pageMode" : @(PSPDFSettingsOptionPageMode), \ + @"spreadFitting" : @(PSPDFSettingsOptionSpreadFitting), \ + @"default" : @(PSPDFSettingsOptionDefault), \ + @"all" : @(PSPDFSettingsOptionAll)} \ + +#define ThumbnailBarMap @{@"none" : @(PSPDFThumbnailBarModeNone), \ + @"default": @(PSPDFThumbnailBarModeFloatingScrubberBar), \ + @"floating" : @(PSPDFThumbnailBarModeFloatingScrubberBar), \ + @"scrubberBar" : @(PSPDFThumbnailBarModeScrubberBar), \ + @"pinned" : @(PSPDFThumbnailBarModeScrubberBar), \ + @"scrollable" : @(PSPDFThumbnailBarModeScrollable)} \ + +#define ScrubberBarTypeMap @{@"horizontal" : @(PSPDFScrubberBarTypeHorizontal), \ + @"verticalLeft" : @(PSPDFScrubberBarTypeVerticalLeft), \ + @"verticalRight" : @(PSPDFScrubberBarTypeVerticalRight)} \ + +#define ThumbnailGroupingMap @{@"automatic" : @(PSPDFThumbnailGroupingAutomatic), \ + @"never" : @(PSPDFThumbnailGroupingNever), \ + @"always" : @(PSPDFThumbnailGroupingAlways)} \ + +#define LinkActionMap @{@"none" : @(PSPDFLinkActionNone), \ + @"alertView" : @(PSPDFLinkActionAlertView), \ + @"openSafari" : @(PSPDFLinkActionOpenSafari), \ + @"inlineBrowser" : @(PSPDFLinkActionInlineBrowser), \ + @"InlineWebViewController" : @(PSPDFLinkActionInlineWebViewController)} \ + +#define DrawCreateModeMap @{@"separate" : @(PSPDFDrawCreateModeSeparate), \ + @"mergeIfPossible" : @(PSPDFDrawCreateModeMergeIfPossible)} \ + +#define BookmarkSortOrderMap @{@"custom" : @(PSPDFBookmarkManagerSortOrderCustom), \ + @"pageBased" : @(PSPDFBookmarkManagerSortOrderPageBased)} \ + @implementation RCTConvert (PSPDFConfiguration) + (PSPDFConfiguration *)PSPDFConfiguration:(id)json { @@ -45,47 +163,32 @@ + (NSDictionary *)processConfigurationOptionsDictionaryForPrefix:(NSDictionary * } RCT_ENUM_CONVERTER(PSPDFScrollDirection, - (@{@"horizontal" : @(PSPDFScrollDirectionHorizontal), - @"vertical" : @(PSPDFScrollDirectionVertical)}), + (ScrollDirectionMap), PSPDFScrollDirectionHorizontal, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFTapAction, - (@{@"none" : @(PSPDFTapActionNone), - @"zoom" : @(PSPDFTapActionZoom), - @"smartZoom" : @(PSPDFTapActionSmartZoom)}), + (DoubleTapActionMap), PSPDFTapActionNone, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFTextSelectionMode, - (@{@"regular" : @(PSPDFTextSelectionModeRegular), - @"simple" : @(PSPDFTextSelectionModeSimple)}), + (TextSelectionModeMap), PSPDFTextSelectionModeRegular, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFBookmarkManagerSortOrder, - (@{@"custom" : @(PSPDFBookmarkManagerSortOrderCustom), - @"pageBased" : @(PSPDFBookmarkManagerSortOrderPageBased)}), + (BookmarkSortOrderMap), PSPDFBookmarkManagerSortOrderPageBased, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFLinkAction, - (@{@"none" : @(PSPDFLinkActionNone), - @"alertView" : @(PSPDFLinkActionAlertView), - @"openSafari" : @(PSPDFLinkActionOpenSafari), - @"inlineBrowser" : @(PSPDFLinkActionInlineBrowser), - @"InlineWebViewController" : @(PSPDFLinkActionInlineWebViewController)}), + (LinkActionMap), PSPDFLinkActionNone, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFUserInterfaceViewMode, - (@{@"automatic" : @(PSPDFUserInterfaceViewModeAutomatic), - @"automaticBorderPages" : @(PSPDFUserInterfaceViewModeAutomaticNoFirstLastPage), - @"automaticNoFirstLastPage" : @(PSPDFUserInterfaceViewModeAutomaticNoFirstLastPage), - @"always" : @(PSPDFUserInterfaceViewModeAlways), - @"alwaysVisible" : @(PSPDFUserInterfaceViewModeAlways), - @"alwaysHidden" : @(PSPDFUserInterfaceViewModeNever), - @"never" : @(PSPDFUserInterfaceViewModeNever)}), + (UserInterfaceViewModeMap), PSPDFUserInterfaceViewModeAutomatic, unsignedIntegerValue) @@ -97,12 +200,7 @@ + (NSDictionary *)processConfigurationOptionsDictionaryForPrefix:(NSDictionary * unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFThumbnailBarMode, - (@{@"none" : @(PSPDFThumbnailBarModeNone), - @"default": @(PSPDFThumbnailBarModeFloatingScrubberBar), - @"floating" : @(PSPDFThumbnailBarModeFloatingScrubberBar), - @"scrubberBar" : @(PSPDFThumbnailBarModeScrubberBar), - @"pinned" : @(PSPDFThumbnailBarModeScrubberBar), - @"scrollable" : @(PSPDFThumbnailBarModeScrollable)}), + (ThumbnailBarMap), PSPDFThumbnailBarModeFloatingScrubberBar, unsignedIntegerValue) @@ -114,55 +212,42 @@ + (NSDictionary *)processConfigurationOptionsDictionaryForPrefix:(NSDictionary * unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFRenderStatusViewPosition, - (@{@"top" : @(PSPDFRenderStatusViewPositionTop), - @"centered" : @(PSPDFRenderStatusViewPositionCentered)}), + (RenderStatusViewPositionMap), PSPDFRenderStatusViewPositionTop, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFPageMode, - (@{@"single" : @(PSPDFPageModeSingle), - @"double" : @(PSPDFPageModeDouble), - @"automatic" : @(PSPDFPageModeAutomatic)}), + (PageModeMap), PSPDFPageModeAutomatic, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFScrubberBarType, - (@{@"horizontal" : @(PSPDFScrubberBarTypeHorizontal), - @"verticalLeft" : @(PSPDFScrubberBarTypeVerticalLeft), - @"verticalRight" : @(PSPDFScrubberBarTypeVerticalRight)}), + (ScrubberBarTypeMap), PSPDFScrubberBarTypeHorizontal, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFThumbnailGrouping, - (@{@"automatic" : @(PSPDFThumbnailGroupingAutomatic), - @"never" : @(PSPDFThumbnailGroupingNever), - @"always" : @(PSPDFThumbnailGroupingAlways)}), + (ThumbnailGroupingMap), PSPDFThumbnailGroupingAutomatic, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFPageTransition, - (@{@"scrollPerSpread" : @(PSPDFPageTransitionScrollPerSpread), - @"scrollContinuous" : @(PSPDFPageTransitionScrollContinuous), - @"curl" : @(PSPDFPageTransitionCurl)}), + (PageTransitionMap), PSPDFPageTransitionScrollPerSpread, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFDrawCreateMode, - (@{@"separate" : @(PSPDFDrawCreateModeSeparate), - @"mergeIfPossible" : @(PSPDFDrawCreateModeMergeIfPossible)}), + (DrawCreateModeMap), PSPDFDrawCreateModeMergeIfPossible, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFSearchMode, - (@{@"modal" : @(PSPDFSearchModeModal), - @"inline" : @(PSPDFSearchModeInline)}), + (SearchModeMap), PSPDFSearchModeModal, unsignedIntegerValue) RCT_ENUM_CONVERTER(PSPDFSignatureSavingStrategy, - (@{@"alwaysSave" : @(PSPDFSignatureSavingStrategyAlwaysSave), - @"neverSave" : @(PSPDFSignatureSavingStrategyNeverSave), - @"saveIfSelected" : @(PSPDFSignatureSavingStrategySaveIfSelected)}), + (SignatureSavingStrategyMap), PSPDFSignatureSavingStrategyAlwaysSave, unsignedIntegerValue) @@ -200,57 +285,25 @@ + (NSDictionary *)processConfigurationOptionsDictionaryForPrefix:(NSDictionary * */ RCT_MULTI_ENUM_CONVERTER(PSPDFAnnotationType, - (@{@"none" : @(PSPDFAnnotationTypeNone), - @"undefined" : @(PSPDFAnnotationTypeUndefined), - PSPDFAnnotationStringLink : @(PSPDFAnnotationTypeLink), - PSPDFAnnotationStringHighlight : @(PSPDFAnnotationTypeHighlight), - PSPDFAnnotationStringStrikeOut : @(PSPDFAnnotationTypeStrikeOut), - PSPDFAnnotationStringUnderline : @(PSPDFAnnotationTypeUnderline), - PSPDFAnnotationStringSquiggly : @(PSPDFAnnotationTypeSquiggly), - PSPDFAnnotationStringFreeText : @(PSPDFAnnotationTypeFreeText), - PSPDFAnnotationStringInk : @(PSPDFAnnotationTypeInk), - PSPDFAnnotationStringSquare : @(PSPDFAnnotationTypeSquare), - PSPDFAnnotationStringCircle : @(PSPDFAnnotationTypeCircle), - PSPDFAnnotationStringLine : @(PSPDFAnnotationTypeLine), - PSPDFAnnotationStringNote : @(PSPDFAnnotationTypeNote), - PSPDFAnnotationStringStamp : @(PSPDFAnnotationTypeStamp), - PSPDFAnnotationStringCaret : @(PSPDFAnnotationTypeCaret), - PSPDFAnnotationStringRichMedia : @(PSPDFAnnotationTypeRichMedia), - PSPDFAnnotationStringScreen : @(PSPDFAnnotationTypeScreen), - PSPDFAnnotationStringWidget : @(PSPDFAnnotationTypeWidget), - PSPDFAnnotationStringFile : @(PSPDFAnnotationTypeFile), - PSPDFAnnotationStringSound : @(PSPDFAnnotationTypeSound), - PSPDFAnnotationStringPolygon : @(PSPDFAnnotationTypePolygon), - PSPDFAnnotationStringPolyLine : @(PSPDFAnnotationTypePolyLine), - PSPDFAnnotationStringPopup : @(PSPDFAnnotationTypePopup), - PSPDFAnnotationStringWatermark : @(PSPDFAnnotationTypeWatermark), - PSPDFAnnotationStringTrapNet : @(PSPDFAnnotationTypeTrapNet), - PSPDFAnnotationString3D : @(PSPDFAnnotationTypeThreeDimensional), - PSPDFAnnotationStringRedaction : @(PSPDFAnnotationTypeRedaction), - @"all" : @(PSPDFAnnotationTypeAll)}), + (TypesShowingColorPresetsMap), PSPDFAnnotationTypeNone, unsignedIntegerValue) RCT_MULTI_ENUM_CONVERTER(PSPDFAppearanceMode, - (@{@"default" : @(PSPDFAppearanceModeDefault), - @"sepia" : @(PSPDFAppearanceModeSepia), - @"night" : @(PSPDFAppearanceModeNight), - @"all" : @(PSPDFAppearanceModeAll)}), + (AppearanceModeMap), PSPDFAppearanceModeDefault, unsignedIntegerValue) RCT_MULTI_ENUM_CONVERTER(PSPDFSettingsOptions, - (@{@"scrollDirection" : @(PSPDFSettingsOptionScrollDirection), - @"pageTransition" : @(PSPDFSettingsOptionPageTransition), - @"appearance" : @(PSPDFSettingsOptionAppearance), - @"brightness" : @(PSPDFSettingsOptionBrightness), - @"pageMode" : @(PSPDFSettingsOptionPageMode), - @"spreadFitting" : @(PSPDFSettingsOptionSpreadFitting), - @"default" : @(PSPDFSettingsOptionDefault), - @"all" : @(PSPDFSettingsOptionAll)}), + (SettingsOptionsMap), PSPDFSettingsOptionAll, unsignedIntegerValue) +RCT_ENUM_CONVERTER(PSPDFConfigurationSpreadFitting, + (SpreadFittingMap), + PSPDFConfigurationSpreadFittingAdaptive, + unsignedIntegerValue) + RCT_MULTI_ENUM_CONVERTER(PSPDFDocumentSharingFileFormatOptions, (@{@"PDF" : @(PSPDFDocumentSharingFileFormatOptionPDF), @"original": @(PSPDFDocumentSharingFileFormatOptionOriginal), @@ -276,6 +329,242 @@ + (NSDictionary *)processConfigurationOptionsDictionaryForPrefix:(NSDictionary * PSPDFDocumentSharingPagesOptionAll, unsignedIntegerValue) ++ (NSArray *)translateSize:(NSString *)input { + return [RCTConvert stringToFloatArray:[[RCTConvert sanitiseSizeString:input] componentsSeparatedByString:@","]]; +} + ++ (NSArray *)stringToFloatArray:(NSArray *)stringArray { + + NSMutableArray *intArray = [NSMutableArray new]; + + for (NSString *item in stringArray) { + [intArray addObject:@([item floatValue])]; + } + + return intArray; +} + ++ (NSString *)sanitiseSizeString:(NSString *)input { + + input = [input stringByReplacingOccurrencesOfString:@"{" withString:@""]; + input = [input stringByReplacingOccurrencesOfString:@"}" withString:@""]; + input = [input stringByReplacingOccurrencesOfString:@" " withString:@""]; + + return input; +} + ++ (NSString *)findKeyForValue:(NSUInteger)value + inDictionary:(NSDictionary *)dictionary { + + NSString *foundKey = @""; + for (NSString* key in [dictionary allKeys]) { + NSNumber *foundValue = [dictionary objectForKey:key]; + if([foundValue isEqual:@(value)]) { + foundKey = key; + break; + } + } + return foundKey; +} + ++ (NSArray *)findKeysForValues:(NSSet *)values + inDictionary:(NSDictionary *)dictionary { + + NSMutableArray *foundKeys = [NSMutableArray new]; + for (NSString *item in values) { + if (dictionary[item]) { + [foundKeys addObject:item]; + } + } + return foundKeys; +} + ++ (BOOL)extractBooleanFrom:(NSUInteger)value + positiveValue:(NSUInteger)positive { + + return value == positive; +} + ++ (NSDictionary *)convertConfiguration:(PSPDFViewController *)viewController { + + PSPDFConfiguration *configuration = viewController.configuration; + + NSMutableDictionary *convertedConfiguration = [NSMutableDictionary new]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.scrollDirection + inDictionary:ScrollDirectionMap] forKey:@"scrollDirection"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.pageTransition + inDictionary:PageTransitionMap] forKey:@"pageTransition"]; + + [convertedConfiguration setObject:@(configuration.textSelectionEnabled) forKey:@"enableTextSelection"]; + + [convertedConfiguration setObject:@(configuration.autosaveEnabled) forKey:@"autosaveEnabled"]; + + [convertedConfiguration setObject:!configuration.autosaveEnabled ? @YES : @NO forKey:@"disableAutomaticSaving"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.signatureSavingStrategy + inDictionary:SignatureSavingStrategyMap] forKey:@"signatureSavingStrategy"]; + + [convertedConfiguration setObject:@(configuration.formElementZoomEnabled) forKey:@"iOSFormElementZoomEnabled"]; + + [convertedConfiguration setObject:@(configuration.imageSelectionEnabled) forKey:@"iOSImageSelectionEnabled"]; + + [convertedConfiguration setObject:@(configuration.textSelectionShouldSnapToWord) forKey:@"iOSTextSelectionShouldSnapToWord"]; + + [convertedConfiguration setObject:@(configuration.freeTextAccessoryViewEnabled) forKey:@"iOSFreeTextAccessoryViewEnabled"]; + + [convertedConfiguration setObject:@(configuration.internalTapGesturesEnabled) forKey:@"iOSInternalTapGesturesEnabled"]; + + [convertedConfiguration setObject:@(configuration.allowBackgroundSaving) forKey:@"iOSAllowBackgroundSaving"]; + + [convertedConfiguration setObject:@(configuration.minimumZoomScale) forKey:@"iOSMinimumZoomScale"]; + + [convertedConfiguration setObject:@(configuration.maximumZoomScale) forKey:@"iOSMaximumZoomScale"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.doubleTapAction + inDictionary:DoubleTapActionMap] forKey:@"iOSDoubleTapAction"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.textSelectionMode + inDictionary:TextSelectionModeMap] forKey:@"iOSTextSelectionMode"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.typesShowingColorPresets + inDictionary:TypesShowingColorPresetsMap] forKey:@"iOSTypesShowingColorPresets"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.pageMode + inDictionary:PageModeMap] forKey:@"pageMode"]; + + [convertedConfiguration setObject:@(configuration.firstPageAlwaysSingle) forKey:@"firstPageAlwaysSingle"]; + + [convertedConfiguration setObject:@(configuration.pageLabelEnabled) forKey:@"showPageLabels"]; + + [convertedConfiguration setObject:@([RCTConvert extractBooleanFrom:configuration.documentLabelEnabled + positiveValue:PSPDFAdaptiveConditionalYES]) forKey:@"documentLabelEnabled"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.spreadFitting + inDictionary:SpreadFittingMap] forKey:@"spreadFitting"]; + + [convertedConfiguration setObject:viewController.appearanceModeManager.appearanceMode == PSPDFAppearanceModeNight ? @YES : @NO forKey:@"invertColors"]; + + [convertedConfiguration setObject:@(configuration.clipToPageBoundaries) forKey:@"iOSClipToPageBoundaries"]; + + [convertedConfiguration setObject:@(configuration.backgroundColor.hexa) forKey:@"iOSBackgroundColor"]; + + [convertedConfiguration setObject:@(configuration.renderAnimationEnabled) forKey:@"iOSRenderAnimationEnabled"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.renderStatusViewPosition + inDictionary:RenderStatusViewPositionMap] forKey:@"iOSRenderStatusViewPosition"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.allowedAppearanceModes + inDictionary:AppearanceModeMap] forKey:@"allowedAppearanceModes"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.userInterfaceViewMode + inDictionary:UserInterfaceViewModeMap] forKey:@"userInterfaceViewMode"]; + + [convertedConfiguration setObject:@([RCTConvert extractBooleanFrom:configuration.searchMode positiveValue:PSPDFSearchModeInline]) forKey:@"inlineSearch"]; + + [convertedConfiguration setObject:@([RCTConvert extractBooleanFrom:configuration.userInterfaceViewMode positiveValue:PSPDFUserInterfaceViewModeNever]) forKey:@"immersiveMode"]; + + [convertedConfiguration setObject:viewController.title == nil ? @"" : viewController.title forKey:@"toolbarTitle"]; + + [convertedConfiguration setObject:@(configuration.shouldHideUserInterfaceOnPageChange) forKey:@"iOSShouldHideUserInterfaceOnPageChange"]; + + [convertedConfiguration setObject:@(configuration.shouldShowUserInterfaceOnViewWillAppear) forKey:@"iOSShouldShowUserInterfaceOnViewWillAppear"]; + + [convertedConfiguration setObject:@(configuration.shouldHideStatusBarWithUserInterface) forKey:@"iOSShouldHideStatusBarWithUserInterface"]; + + [convertedConfiguration setObject:@(configuration.shouldHideNavigationBarWithUserInterface) forKey:@"iOSShouldHideNavigationBarWithUserInterface"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.searchMode + inDictionary:SearchModeMap] forKey:@"iOSSearchMode"]; + + [convertedConfiguration setObject:@(configuration.scrollOnEdgeTapEnabled) forKey:@"iOSScrollOnEdgeTapEnabled"]; + + [convertedConfiguration setObject:@(configuration.scrollOnEdgeTapMargin) forKey:@"iOSScrollOnEdgeTapMargin"]; + + [convertedConfiguration setObject:@(configuration.useParentNavigationBar) forKey:@"iOSUseParentNavigationBar"]; + + [convertedConfiguration setObject:@(configuration.allowToolbarTitleChange) forKey:@"iOSAllowToolbarTitleChange"]; + + [convertedConfiguration setObject:@(configuration.shouldHideStatusBar) forKey:@"iOSShouldHideStatusBar"]; + + [convertedConfiguration setObject:@(configuration.showBackActionButton) forKey:@"iOSShowBackActionButton"]; + + [convertedConfiguration setObject:@(configuration.showForwardActionButton) forKey:@"iOSShowForwardActionButton"]; + + [convertedConfiguration setObject:@(configuration.showBackForwardActionButtonLabels) forKey:@"iOSShowBackForwardActionButtonLabels"]; + + [convertedConfiguration setObject:@(configuration.searchResultZoomScale) forKey:@"iOSSearchResultZoomScale"]; + + [convertedConfiguration setObject:[RCTConvert translateSize:NSStringFromUIEdgeInsets(configuration.additionalScrollViewFrameInsets)] forKey:@"iOSAdditionalScrollViewFrameInsets"]; + [convertedConfiguration setObject:[RCTConvert translateSize:NSStringFromUIEdgeInsets(configuration.additionalContentInsets)] forKey:@"iOSAdditionalContentInsets"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.allowedMenuActions + inDictionary:AllowedMenuActionsMap] forKey:@"iOSAllowedMenuActions"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.settingsOptions + inDictionary:SettingsOptionsMap] forKey:@"iOSSettingsOptions"]; + + [convertedConfiguration setObject:@(configuration.shadowEnabled) forKey:@"iOSShadowEnabled"]; + + [convertedConfiguration setObject:@(configuration.shadowOpacity) forKey:@"iOSShadowOpacity"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.thumbnailBarMode + inDictionary:ThumbnailBarMap] forKey:@"showThumbnailBar"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.scrubberBarType + inDictionary:ScrubberBarTypeMap] forKey:@"iOSScrubberBarType"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.thumbnailGrouping + inDictionary:ThumbnailGroupingMap] forKey:@"iOSThumbnailGrouping"]; + + [convertedConfiguration setObject:[RCTConvert translateSize:NSStringFromCGSize(configuration.thumbnailSize)] forKey:@"iOSThumbnailSize"]; + + [convertedConfiguration setObject:@(configuration.thumbnailInteritemSpacing) forKey:@"iOSThumbnailInteritemSpacing"]; + + [convertedConfiguration setObject:@(configuration.thumbnailLineSpacing) forKey:@"iOSThumbnailLineSpacing"]; + + [convertedConfiguration setObject:[RCTConvert translateSize:NSStringFromUIEdgeInsets(configuration.thumbnailMargin)] forKey:@"iOSThumbnailMargin"]; + + [convertedConfiguration setObject:@(configuration.shouldCacheThumbnails) forKey:@"iOSShouldCacheThumbnails"]; + + [convertedConfiguration setObject:[RCTConvert findKeysForValues:configuration.editableAnnotationTypes + inDictionary:TypesShowingColorPresetsMap] forKey:@"editableAnnotationTypes"]; + + // If there are editableAnnotationTypes set, returning enableAnnotationEditing = true would enable all annotations the next time the Configuration is applied to a new PDFViewController instance. So include only if editableAnnotationTypes are 0 or enableAnnotationEditing was explicitly disabled. + if (configuration.editableAnnotationTypes.count == 0) { + [convertedConfiguration setObject:@NO forKey:@"enableAnnotationEditing"]; + } + + [convertedConfiguration setObject:[configuration.editableAnnotationTypes containsObject:PSPDFAnnotationStringWidget] ? @YES : @NO forKey:@"enableFormEditing"]; + + [convertedConfiguration setObject:@(configuration.shouldAskForAnnotationUsername) forKey:@"iOSShouldAskForAnnotationUsername"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.linkAction + inDictionary:LinkActionMap] forKey:@"iOSLinkAction"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.drawCreateMode + inDictionary:DrawCreateModeMap] forKey:@"iOSDrawCreateMode"]; + + [convertedConfiguration setObject:@(configuration.annotationGroupingEnabled) forKey:@"iOSAnnotationGroupingEnabled"]; + + [convertedConfiguration setObject:@(configuration.naturalDrawingAnnotationEnabled) forKey:@"iOSNaturalDrawingAnnotationEnabled"]; + + [convertedConfiguration setObject:@(configuration.naturalSignatureDrawingEnabled) forKey:@"iOSNaturalSignatureDrawingEnabled"]; + + [convertedConfiguration setObject:@(configuration.annotationEntersEditModeAfterSecondTapEnabled) forKey:@"iOSAnnotationEntersEditModeAfterSecondTapEnabled"]; + + [convertedConfiguration setObject:@(configuration.createAnnotationMenuEnabled) forKey:@"iOSCreateAnnotationMenuEnabled"]; + + [convertedConfiguration setObject:@(configuration.annotationAnimationDuration) forKey:@"iOSAnnotationAnimationDuration"]; + + [convertedConfiguration setObject:@(configuration.soundAnnotationTimeLimit) forKey:@"iOSSoundAnnotationTimeLimit"]; + + [convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.bookmarkSortOrder + inDictionary:BookmarkSortOrderMap] forKey:@"iOSBookmarkSortOrder"]; + + return convertedConfiguration; +} @end @@ -302,6 +591,10 @@ - (void)setupFromJSON:(id)json { SET(autosaveEnabled, BOOL) SET(allowBackgroundSaving, BOOL) SET(signatureSavingStrategy, PSPDFSignatureSavingStrategy) + if ([dictionary[@"signatureSavingStrategy"] isEqualToString:@"alwaysSave"] || + [dictionary[@"signatureSavingStrategy"] isEqualToString:@"saveIfSelected"] ) { + self.signatureStore = [PSPDFKeychainSignatureStore new]; + } SET(minimumZoomScale, float) SET(maximumZoomScale, float) SET(doubleTapAction, PSPDFTapAction) @@ -317,6 +610,7 @@ - (void)setupFromJSON:(id)json { SET(pageMode, PSPDFPageMode) SET(firstPageAlwaysSingle, BOOL) SET(clipToPageBoundaries, BOOL) + SET(spreadFitting, PSPDFConfigurationSpreadFitting) SET(backgroundColor, UIColor) SET(renderAnimationEnabled, BOOL) SET(renderStatusViewPosition, PSPDFRenderStatusViewPosition) diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.h b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.h index db98807d..f53465a5 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.h @@ -1,5 +1,5 @@ // -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2016-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.m b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.m index 06a4d767..e6657af9 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.m @@ -1,5 +1,5 @@ // -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2016-2024 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. @@ -29,6 +29,9 @@ + (NSURL*) parseURL: (NSString*) urlString { NSURL* url; if ([urlString hasPrefix: @"/"] || [urlString containsString: @"file:/"]) { + if ([urlString hasPrefix:@"file:///"]) { + urlString = [urlString substringFromIndex:7]; + } url = [NSURL fileURLWithPath: urlString]; } diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.h b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.h index a3a8b53a..345b8b9f 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.h @@ -1,5 +1,5 @@ // -// Copyright © 2019-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2019-2024 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. @@ -14,5 +14,6 @@ @interface RCTConvert (PSPDFViewMode) + (PSPDFViewMode)PSPDFViewMode:(NSString *)viewMode; ++ (NSString *)PSPDFViewModeString:(PSPDFViewMode)viewMode; @end diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.m b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.m index c4422cae..4af02ebc 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.m @@ -1,5 +1,5 @@ // -// Copyright © 2019-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2019-2024 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. @@ -23,4 +23,16 @@ + (PSPDFViewMode)PSPDFViewMode:(NSString *)viewMode { } } ++ (NSString *)PSPDFViewModeString:(PSPDFViewMode)viewMode { + if (viewMode == PSPDFViewModeDocument) { + return @"document"; + } else if (viewMode == PSPDFViewModeThumbnails) { + return @"thumbnails"; + } else if (viewMode == PSPDFViewModeDocumentEditor) { + return @"documentEditor"; + } else { + return @"document"; + } +} + @end diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.h b/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.h index d87f9bb9..39d52e26 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.h @@ -1,5 +1,5 @@ // -// Copyright © 2019-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2019-2024 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. diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.m b/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.m index c066718a..9ea9fdd2 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.m @@ -1,5 +1,5 @@ // -// Copyright © 2019-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2019-2024 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. diff --git a/ios/RCTPSPDFKit/InstantDocumentInfo.swift b/ios/RCTPSPDFKit/InstantDocumentInfo.swift index 3bcb8a23..714362e5 100644 --- a/ios/RCTPSPDFKit/InstantDocumentInfo.swift +++ b/ios/RCTPSPDFKit/InstantDocumentInfo.swift @@ -2,7 +2,7 @@ // InstantDocumentInfo.swift // PSPDFKit // -// Copyright © 2017-2022 PSPDFKit GmbH. All rights reserved. +// Copyright © 2017-2024 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. diff --git a/ios/RCTPSPDFKit/InstantDocumentViewController.swift b/ios/RCTPSPDFKit/InstantDocumentViewController.swift index 49d66068..bfeaffb8 100644 --- a/ios/RCTPSPDFKit/InstantDocumentViewController.swift +++ b/ios/RCTPSPDFKit/InstantDocumentViewController.swift @@ -1,5 +1,5 @@ // -// Copyright © 2019-2022 PSPDFKit GmbH. All rights reserved. +// Copyright © 2019-2024 PSPDFKit GmbH. All rights reserved. // // The PSPDFKit Sample applications are licensed with a modified BSD license. // Please see License for details. This notice may not be removed from this file. @@ -35,7 +35,7 @@ public class InstantDocumentViewController: InstantViewController { // Store document info for sharing later. self.documentInfo = documentInfo - // Tell Instant to download the document from Web examples server’s PSPDFKit Server instance. + // Tell Instant to download the document from Web examples server’s PSPDFKit Document Engine instance. do { try documentDescriptor.download(usingJWT: documentInfo.jwt) } catch InstantError.alreadyDownloaded { diff --git a/ios/RCTPSPDFKit/RCTPSPDFKit-Bridging-Header.h b/ios/RCTPSPDFKit/RCTPSPDFKit-Bridging-Header.h index 27453aea..9777b57f 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKit-Bridging-Header.h +++ b/ios/RCTPSPDFKit/RCTPSPDFKit-Bridging-Header.h @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitManager.h b/ios/RCTPSPDFKit/RCTPSPDFKitManager.h index d73b691c..8ab287be 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitManager.h +++ b/ios/RCTPSPDFKit/RCTPSPDFKitManager.h @@ -1,5 +1,5 @@ // -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2016-2024 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. diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitManager.m b/ios/RCTPSPDFKit/RCTPSPDFKitManager.m index 2b2c88d9..a7cabcc4 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitManager.m +++ b/ios/RCTPSPDFKit/RCTPSPDFKitManager.m @@ -1,5 +1,5 @@ // -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2016-2024 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. diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitView.h b/ios/RCTPSPDFKit/RCTPSPDFKitView.h index 1c935eb2..7c4e3c41 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitView.h +++ b/ios/RCTPSPDFKit/RCTPSPDFKitView.h @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. @@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) RCTBubblingEventBlock onAnnotationsChanged; @property (nonatomic, copy) RCTBubblingEventBlock onStateChanged; @property (nonatomic, copy) RCTBubblingEventBlock onDocumentLoaded; +@property (nonatomic, copy) RCTBubblingEventBlock onCustomToolbarButtonTapped; @property (nonatomic, copy, nullable) NSArray *availableFontNames; @property (nonatomic, copy, nullable) NSString *selectedFontName; @property (nonatomic) BOOL showDownloadableFonts; diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitView.m b/ios/RCTPSPDFKit/RCTPSPDFKitView.m index 8a3e9426..9b11d918 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitView.m +++ b/ios/RCTPSPDFKit/RCTPSPDFKitView.m @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. @@ -22,6 +22,7 @@ @interface RCTPSPDFKitView () *)items forViewMode:(nullable NSString *) viewMode animated:(BOOL)animated { +- (void)setLeftBarButtonItems:(nullable NSArray *)items forViewMode:(nullable NSString *) viewMode animated:(BOOL)animated { NSMutableArray *leftItems = [NSMutableArray array]; - for (NSString *barButtonItemString in items) { - UIBarButtonItem *barButtonItem = [RCTConvert uiBarButtonItemFrom:barButtonItemString forViewController:self.pdfController]; - if (barButtonItem && ![self.pdfController.navigationItem.rightBarButtonItems containsObject:barButtonItem]) { - [leftItems addObject:barButtonItem]; - } + for (id item in items) { + if ([item isKindOfClass:[NSString class]]) { + UIBarButtonItem *barButtonItem = [RCTConvert uiBarButtonItemFrom:item forViewController:self.pdfController]; + if (barButtonItem && ![self.pdfController.navigationItem.rightBarButtonItems containsObject:barButtonItem]) { + [leftItems addObject:barButtonItem]; + } + } else if ([item isKindOfClass:[NSDictionary class]]) { + UIImage *image = [[UIImage imageNamed:[item objectForKey:@"image"]] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(handleCustomBarButtonEvent:)]; + [_customBarButtons setObject:barButtonItem forKey:[item objectForKey:@"id"]]; + if (barButtonItem && ![self.pdfController.navigationItem.rightBarButtonItems containsObject:barButtonItem]) { + [leftItems addObject:barButtonItem]; + } + } } if (viewMode.length) { @@ -419,13 +430,23 @@ - (void)setLeftBarButtonItems:(nullable NSArray *)items forViewMode } - (void)setRightBarButtonItems:(nullable NSArray *)items forViewMode:(nullable NSString *) viewMode animated:(BOOL)animated { - NSMutableArray *rightItems = [NSMutableArray array]; - for (NSString *barButtonItemString in items) { - UIBarButtonItem *barButtonItem = [RCTConvert uiBarButtonItemFrom:barButtonItemString forViewController:self.pdfController]; - if (barButtonItem && ![self.pdfController.navigationItem.leftBarButtonItems containsObject:barButtonItem]) { - [rightItems addObject:barButtonItem]; + NSMutableArray *rightItems = [NSMutableArray array]; + for (id item in items) { + if ([item isKindOfClass:[NSString class]]) { + UIBarButtonItem *barButtonItem = [RCTConvert uiBarButtonItemFrom:item forViewController:self.pdfController]; + if (barButtonItem && ![self.pdfController.navigationItem.leftBarButtonItems containsObject:barButtonItem]) { + [rightItems addObject:barButtonItem]; + } + } else if ([item isKindOfClass:[NSDictionary class]]) { + UIImage *image = [[UIImage imageNamed:[item objectForKey:@"image"]] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(handleCustomBarButtonEvent:)]; + [_customBarButtons setObject:barButtonItem forKey:[item objectForKey:@"id"]]; + if (barButtonItem && ![self.pdfController.navigationItem.leftBarButtonItems containsObject:barButtonItem]) { + [rightItems addObject:barButtonItem]; + } + } } - } if (viewMode.length) { [self.pdfController.navigationItem setRightBarButtonItems:[rightItems copy] forViewMode:[RCTConvert PSPDFViewMode:viewMode] animated:animated]; @@ -490,12 +511,39 @@ - (void)onStateChangedForPDFViewController:(PSPDFViewController *)pdfController [barButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem * _Nonnull barButtonItem, NSUInteger idx, BOOL * _Nonnull stop) { NSString *buttonNameString = [RCTConvert stringBarButtonItemFrom:barButtonItem forViewController:self.pdfController]; if (buttonNameString) { - [barButtonItemsString addObject:buttonNameString]; + [barButtonItemsString addObject:buttonNameString]; + } else { + NSString *customId = [self findCustomButtonID:barButtonItem]; + if (customId != nil) { + [barButtonItemsString addObject:customId]; + } } }]; return [barButtonItemsString copy]; } +- (NSString *)findCustomButtonID:(UIBarButtonItem *)barButton { + NSString *foundKey = nil; + NSArray *keys = [_customBarButtons allKeys]; + for (NSString *key in keys) { + if ([_customBarButtons objectForKey:key] == barButton) { + foundKey = key; + break; + } + } + return foundKey; +} + +- (void)handleCustomBarButtonEvent:(id)sender { + UIBarButtonItem *barButton = (UIBarButtonItem *)sender; + if (self.onCustomToolbarButtonTapped) { + NSString *customId = [self findCustomButtonID:barButton]; + if (customId != nil) { + self.onCustomToolbarButtonTapped(@{@"id" : customId}); + } + } +} + @end @implementation RCTPSPDFKitViewController diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.h b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.h index 1e236e97..5fd0467b 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.h +++ b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.h @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m index bc15081d..08a3400d 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m +++ b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. @@ -13,6 +13,7 @@ #import "RCTConvert+PSPDFDocument.h" #import "RCTConvert+PSPDFAnnotationToolbarConfiguration.h" #import "RCTConvert+PSPDFViewMode.h" +#import "RCTConvert+PSPDFConfiguration.h" #import "RCTPSPDFKitView.h" #if __has_include("PSPDFKitReactNativeiOS-Swift.h") #import "PSPDFKitReactNativeiOS-Swift.h" @@ -55,14 +56,23 @@ @implementation RCTPSPDFKitViewManager } view.pdfController.pageIndex = view.pageIndex; + if ([_configuration objectForKey:@"documentPassword"]) { + [view.pdfController.document unlockWithPassword:[_configuration objectForKey:@"documentPassword"]]; + } - // Update measurement scale and precision after document is created and remove it from memory after reading - [PspdfkitMeasurementConvertor setConfig: _configuration document: view.pdfController.document]; - _configuration = nil; - if(view.onDocumentLoaded) { - view.onDocumentLoaded(@{}); - } + // Apply any measurementValueConfigurations once the document is loaded + if ([_configuration objectForKey:@"measurementValueConfigurations"]) { + NSArray *configs = [_configuration objectForKey:@"measurementValueConfigurations"]; + for (NSDictionary *config in configs) { + [PspdfkitMeasurementConvertor addMeasurementValueConfigurationWithDocument:view.pdfController.document + configuration:config]; + } + } + _configuration = nil; + if(view.onDocumentLoaded) { + view.onDocumentLoaded(@{}); } + } } RCT_CUSTOM_VIEW_PROPERTY(pageIndex, PSPDFPageIndex, RCTPSPDFKitView) { @@ -187,6 +197,8 @@ - (void)postProcessConfigurationOptionsWithJSON:(id)json forPDFViewController:(P RCT_EXPORT_VIEW_PROPERTY(onDocumentLoaded, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onCustomToolbarButtonTapped, RCTBubblingEventBlock) + RCT_CUSTOM_VIEW_PROPERTY(availableFontNames, NSArray, RCTPSPDFKitView) { if (json && [RCTConvert NSArray:json]) { view.availableFontNames = [RCTConvert NSArray:json]; @@ -208,6 +220,24 @@ - (void)postProcessConfigurationOptionsWithJSON:(id)json forPDFViewController:(P } } +RCT_CUSTOM_VIEW_PROPERTY(toolbar, NSDictionary, RCTPSPDFKitView) { + if (json) { + NSDictionary *navigation = [RCTConvert NSDictionary:json]; + + if ([navigation objectForKey:@"leftBarButtonItems"] != nil) { + [view setLeftBarButtonItems:[[navigation objectForKey:@"leftBarButtonItems"] objectForKey:@"buttons"] + forViewMode:[[navigation objectForKey:@"leftBarButtonItems"] objectForKey:@"viewMode"] + animated:[[navigation objectForKey:@"leftBarButtonItems"] objectForKey:@"animated"]]; + } + + if ([navigation objectForKey:@"rightBarButtonItems"] != nil) { + [view setRightBarButtonItems:[[navigation objectForKey:@"rightBarButtonItems"] objectForKey:@"buttons"] + forViewMode:[[navigation objectForKey:@"rightBarButtonItems"] objectForKey:@"viewMode"] + animated:[[navigation objectForKey:@"rightBarButtonItems"] objectForKey:@"animated"]]; + } + } +} + RCT_EXPORT_METHOD(enterAnnotationCreationMode:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; @@ -416,45 +446,91 @@ - (void)postProcessConfigurationOptionsWithJSON:(id)json forPDFViewController:(P }); } -RCT_EXPORT_METHOD(setMeasurementConfig:(nullable NSDictionary*)config reactTag:(nonnull NSNumber*) reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_main_queue(), ^{ - RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - PSPDFMeasurementScale* scaleConfig = [PspdfkitMeasurementConvertor getScaleConfig: config]; - if (scaleConfig != nil) { - component.pdfController.document.measurementScale = scaleConfig; - } - - if([config objectForKey: @"precision"] != nil) { - NSInteger precisionUnit = [PspdfkitMeasurementConvertor getPrecisionInt: [config objectForKey: @"precision"]]; +RCT_EXPORT_METHOD(setToolbar:(NSDictionary *)toolbar reactTag:(nonnull NSNumber *)reactTag) { + dispatch_async(dispatch_get_main_queue(), ^{ + RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; + + if ([toolbar objectForKey:@"leftBarButtonItems"] != nil) { + [component setLeftBarButtonItems:[[toolbar objectForKey:@"leftBarButtonItems"] objectForKey:@"buttons"] + forViewMode:[[toolbar objectForKey:@"leftBarButtonItems"] objectForKey:@"viewMode"] + animated:[[toolbar objectForKey:@"leftBarButtonItems"] objectForKey:@"animated"]]; + } + + if ([toolbar objectForKey:@"rightBarButtonItems"] != nil) { + [component setRightBarButtonItems:[[toolbar objectForKey:@"rightBarButtonItems"] objectForKey:@"buttons"] + forViewMode:[[toolbar objectForKey:@"rightBarButtonItems"] objectForKey:@"viewMode"] + animated:[[toolbar objectForKey:@"rightBarButtonItems"] objectForKey:@"animated"]]; + } + }); +} - component.pdfController.document.measurementPrecision = precisionUnit; - } - }); +RCT_EXPORT_METHOD(getToolbar:(nullable NSString *)viewMode reactTag:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { + dispatch_async(dispatch_get_main_queue(), ^{ + RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; + + NSArray *leftItems = [component getLeftBarButtonItemsForViewMode:viewMode]; + NSArray *rightItems = [component getRightBarButtonItemsForViewMode:viewMode]; + + NSDictionary *toolbar = @{ + @"viewMode" : viewMode == nil ? [RCTConvert PSPDFViewModeString:component.pdfController.viewMode] : viewMode, + @"leftBarButtonItems" : leftItems, + @"rightBarButtonItems" : rightItems + }; + + if (toolbar) { + resolve(toolbar); + } else { + reject(@"error", @"Failed to retrieve toolbar.", nil); + } + }); } -RCT_EXPORT_METHOD(setMeasurementScale:(nullable NSDictionary*)config reactTag:(nonnull NSNumber*) reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { +RCT_EXPORT_METHOD(setMeasurementValueConfigurations:(nullable NSArray*)configs reactTag:(nonnull NSNumber*)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - PSPDFMeasurementScale* scaleConfig = [PspdfkitMeasurementConvertor getScaleConfig: config]; - if (scaleConfig != nil) { - component.pdfController.document.measurementScale = scaleConfig; + + BOOL response = true; + for (NSDictionary *config in configs) { + BOOL result = [PspdfkitMeasurementConvertor addMeasurementValueConfigurationWithDocument:component.pdfController.document + configuration:config]; + if (result == false ) { + response = false; + } } + // If any of the config in the array failed to set, reject the promise + response ? resolve(@YES) : reject(@"error", @"Failed to set all measurement configuration.", nil); }); } -RCT_EXPORT_METHOD(setMeasurementPrecision:(NSString*)precision reactTag:(nonnull NSNumber*) reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_main_queue(), ^{ - RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - NSInteger precisionUnit = [PspdfkitMeasurementConvertor getPrecisionInt: precision]; +RCT_EXPORT_METHOD(getMeasurementValueConfigurations:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { + dispatch_async(dispatch_get_main_queue(), ^{ + RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; + NSArray *result = [PspdfkitMeasurementConvertor getMeasurementValueConfigurationsWithDocument:component.pdfController.document]; + NSDictionary *configs = [NSDictionary dictionaryWithObject:result + forKey:@"measurementValueConfigurations"]; + if (configs) { + resolve(configs); + } else { + reject(@"error", @"Failed to retrieve Measurement configuration.", nil); + } + }); +} - component.pdfController.document.measurementPrecision = precisionUnit; - }); +RCT_EXPORT_METHOD(getConfiguration:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { + dispatch_async(dispatch_get_main_queue(), ^{ + RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; + NSDictionary *configuration = [RCTConvert convertConfiguration:component.pdfController]; + if (configuration) { + resolve(configuration); + } else { + reject(@"error", @"Failed to retrieve configuration.", nil); + } + }); } - (UIView *)view { return [[RCTPSPDFKitView alloc] init]; } - @end @implementation CustomFontPickerViewController diff --git a/ios/RCTPSPDFKit/RNConfigurationHelper.swift b/ios/RCTPSPDFKit/RNConfigurationHelper.swift index 76d356c8..20689ea6 100644 --- a/ios/RCTPSPDFKit/RNConfigurationHelper.swift +++ b/ios/RCTPSPDFKit/RNConfigurationHelper.swift @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/RNFileHelper.swift b/ios/RCTPSPDFKit/RNFileHelper.swift index e6c89937..970bbebd 100644 --- a/ios/RCTPSPDFKit/RNFileHelper.swift +++ b/ios/RCTPSPDFKit/RNFileHelper.swift @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/RNProcessor.m b/ios/RCTPSPDFKit/RNProcessor.m index 12ce0c4c..749ffece 100644 --- a/ios/RCTPSPDFKit/RNProcessor.m +++ b/ios/RCTPSPDFKit/RNProcessor.m @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/RNProcessor.swift b/ios/RCTPSPDFKit/RNProcessor.swift index 27d3b65b..a0445296 100644 --- a/ios/RCTPSPDFKit/RNProcessor.swift +++ b/ios/RCTPSPDFKit/RNProcessor.swift @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. diff --git a/ios/RCTPSPDFKit/UIColor.swift b/ios/RCTPSPDFKit/UIColor.swift index 02043884..ef26c70f 100644 --- a/ios/RCTPSPDFKit/UIColor.swift +++ b/ios/RCTPSPDFKit/UIColor.swift @@ -1,5 +1,5 @@ // -// Copyright © 2018-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2018-2024 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. @@ -95,4 +95,13 @@ extension UIColor { alpha: alpha ) } + + @objc public var hexa: Int { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + getRed(&red, green: &green, blue: &blue, alpha: &alpha) + return Int(alpha * 255) << 24 + + Int(red * 255) << 16 + + Int(green * 255) << 8 + + Int(blue * 255) + } } diff --git a/jsdoc.json b/jsdoc.json index e74065a3..091c7ce5 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -1,7 +1,7 @@ { "recurseDepth": 10, "source": { - "include": ["index.js"], + "include": ["index.js", "./lib/"], "includePattern": ".js$", "excludePattern": "(node_modules/|docs)" }, diff --git a/lib/configuration/PDFConfiguration.js b/lib/configuration/PDFConfiguration.js new file mode 100644 index 00000000..e1c00d2a --- /dev/null +++ b/lib/configuration/PDFConfiguration.js @@ -0,0 +1,604 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PDFConfiguration = void 0; +/** + * @namespace PDFConfiguration + * @property { PDFConfiguration.ScrollDirection } [scrollDirection] Configures the direction of page scrolling in the document view. + * @property { PDFConfiguration.PageTransition } [pageTransition] Configures the page scrolling mode. Note that ```curl``` mode is only available for iOS and will be ignored on Android. + * @property { string } [documentPassword] The password to unlock the document. + * @property { PDFConfiguration.BooleanType } [enableTextSelection] Allow / disallow text selection. + * @property { PDFConfiguration.BooleanType } [autosaveEnabled] Determines whether PSPDFKit should save automatically in response to [certain UI triggers][], such as the app entering the background or the view disappearing. + * @property { PDFConfiguration.BooleanType } [disableAutomaticSaving] Determines whether PSPDFKit should save automatically in response to certain UI triggers, such as the app entering the background or the view disappearing. + * @property { PDFConfiguration.SignatureSavingStrategy } [signatureSavingStrategy] Determines whether signatures should be saved after creation. + * @property { PDFConfiguration.BooleanType } [iOSShouldScrollToChangedPage] Scrolls to the affected page during an undo / redo operation. + * @property { PDFConfiguration.BooleanType } [iOSFormElementZoomEnabled] Option to automatically focus on selected form elements. + * @property { PDFConfiguration.BooleanType } [iOSImageSelectionEnabled] Allow / disallow image selection. + * @property { PDFConfiguration.BooleanType } [iOSTextSelectionShouldSnapToWord] Configure if text selection should snap to words. + * @property { PDFConfiguration.BooleanType } [iOSFreeTextAccessoryViewEnabled] Shows a toolbar with text editing options above the keyboard while editing free text annotations. + * @property { PDFConfiguration.BooleanType } [iOSInternalTapGesturesEnabled] Enable / disable all internal gesture recognizers. + * @property { PDFConfiguration.BooleanType } [iOSAllowBackgroundSaving] Determines whether automatic saving should happen on a background thread. + * @property { number } [iOSMinimumZoomScale] Minimum zoom scale for the scroll view. + * @property { number } [iOSMaximumZoomScale] Maximum zoom scale for the scroll view. + * @property { PDFConfiguration.IOSDoubleTapAction } [iOSDoubleTapAction] Maximum zoom scale for the scroll view. + * @property { PDFConfiguration.IOSTypesShowingColorPresets[] } [iOSTypesShowingColorPresets] Shows a custom cell with configurable color presets for the provided annotation types. + * @property { PDFConfiguration.PageMode } [pageMode] The document PageMode. + * @property { PDFConfiguration.BooleanType } [firstPageAlwaysSingle] Option to show the first page separately. + * @property { PDFConfiguration.BooleanType } [showPageLabels] Displays the current page number. + * @property { PDFConfiguration.BooleanType } [documentLabelEnabled] Shows an overlay displaying the document name. + * @property { PDFConfiguration.SpreadFitting } [spreadFitting] Controls the page fitting mode. ```adaptive``` mode only works on iOS and has no effect on Android. + * @property { PDFConfiguration.BooleanType } [invertColors] Inverts the document color if ```true```. + * @property { PDFConfiguration.BooleanType } [androidGrayScale] Converts the document colors to grayscale. + * @property { PDFConfiguration.BooleanType } [iOSClipToPageBoundaries] Option to clip content to page boundaries. + * @property { any } [iOSBackgroundColor] Background color behind the page view. + * @property { PDFConfiguration.BooleanType } [iOSRenderAnimationEnabled] Shows a ```UIActivityIndicatorView``` in the top-right corner while the page is rendering. + * @property { PDFConfiguration.IOSRenderStatusViewPosition } [iOSRenderStatusViewPosition] Position of the render status view. + * @property { PDFConfiguration.IOSAllowedAppearanceModes } [iOSAllowedAppearanceModes] Allowed appearance modes for ```BrightnessViewController```. + * @property { PDFConfiguration.UserInterfaceViewMode } [userInterfaceViewMode] Configures the user interface visibility. + * @property { PDFConfiguration.BooleanType } [inlineSearch] Sets the type of search bar to be inline or modular. + * @property { PDFConfiguration.BooleanType } [immersiveMode] Hides the user interface if set to ```true```. + * @property { string } [toolbarTitle] Sets the title of the toolbar. Note: For iOS, you need to set ```documentLabelEnabled```, ```iOSUseParentNavigationBar```, and ```iOSAllowToolbarTitleChange``` to false in your configuration before setting the custom title. + * @property { PDFConfiguration.BooleanType } [androidShowSearchAction] Enables / disables document search functionality. + * @property { PDFConfiguration.BooleanType } [androidShowOutlineAction] Enables an outline menu in the activity. + * @property { PDFConfiguration.BooleanType } [androidShowBookmarksAction] Enables the display of bookmarks. + * @property { PDFConfiguration.BooleanType } [androidShowShareAction] Enables the display of share features. + * @property { PDFConfiguration.BooleanType } [androidShowPrintAction] Enables the printing option in the menu (if applicable) for the document and the device. + * @property { PDFConfiguration.BooleanType } [androidShowDocumentInfoView] Enables the display of document information. + * @property { PDFConfiguration.BooleanType } [androidShowSettingsMenu] Enables the display of the settings menu. + * @property { PDFConfiguration.BooleanType } [iOSShouldHideUserInterfaceOnPageChange] Option to hide / show the user interface when changing pages. + * @property { PDFConfiguration.BooleanType } [iOSShouldShowUserInterfaceOnViewWillAppear] Option to hide / show the user interface when the page appears. + * @property { PDFConfiguration.BooleanType } [iOSShouldHideStatusBarWithUserInterface] Option to hide / show the status bar with the user interface. + * @property { PDFConfiguration.BooleanType } [iOSShouldHideNavigationBarWithUserInterface] Option to hide / show the navigation bar with the user interface. + * @property { PDFConfiguration.IOSSearchMode } [iOSSearchMode] Sets the type of search bar to be inline or modal. + * @property { PDFConfiguration.BooleanType } [iOSScrollOnEdgeTapEnabled] Determines whether tapping on leading / trailing edges of the document view should trigger changing to the previous / next page. + * @property { number } [iOSScrollOnEdgeTapMargin] The margin in points from the view’s sides in which tapping should trigger scrolling to the previous / next page. + * @property { PDFConfiguration.BooleanType } [iOSUseParentNavigationBar] Set this to true to allow this controller to access the parent ```navigationBar``` / ```navigationController``` to add custom buttons. + * @property { PDFConfiguration.BooleanType } [iOSAllowToolbarTitleChange] Allow PSPDFKit to change the title of this view controller. + * @property { PDFConfiguration.BooleanType } [iOSShouldHideStatusBar] If ```true```, the status bar will always remain hidden (regardless of the ```shouldHideStatusBarWithUserInterface``` setting). + * @property { PDFConfiguration.BooleanType } [iOSShowBackActionButton] Shows a floating back button in the lower part of the screen. + * @property { PDFConfiguration.BooleanType } [iOSShowForwardActionButton] Shows a floating forward button in the lower part of the screen. + * @property { PDFConfiguration.BooleanType } [iOSShowBackForwardActionButtonLabels] Adds text labels representing the destination name to the back and forward buttons. + * @property { number } [iOSSearchResultZoomScale] Increase this to zoom to the search result. + * @property { any } [iOSAdditionalScrollViewFrameInsets] Additional insets to apply to the document scroll view's frame. + * @property { any } [iOSAdditionalContentInsets] Additional insets to apply to the layout's content. + * @property { PDFConfiguration.IOSAllowedMenuActions } [iOSAllowedMenuActions] May be used to customize other displayed menu actions when text is selected. + * @property { PDFConfiguration.IOSSettingsOptions[] } [iOSSettingsOptions] Options that will be presented by ```PDFSettingsViewController```. Defaults to ```.default```. + * @property { PDFConfiguration.BooleanType } [iOSShadowEnabled] Enable / disable page shadow. + * @property { number } [iOSShadowOpacity] Set the default ```shadowOpacity```. + * @property { PDFConfiguration.ShowThumbnailBar } [showThumbnailBar] Thumbnail bar mode controls the display of page thumbnails viewing a document. + * @property { PDFConfiguration.BooleanType } [androidShowThumbnailGridAction] Displays an action bar icon to show a grid of thumbnail pages. + * @property { PDFConfiguration.IOSScrubberBarType } [iOSScrubberBarType] Controls the placement of the scrubber bar. + * @property { PDFConfiguration.IOSThumbnailGrouping } [iOSThumbnailGrouping] Option to set the grouping of thumbnails. + * @property { any } [iOSThumbnailSize] Configure the size of the thumbnail. + * @property { number } [iOSThumbnailInteritemSpacing] Configure the spacing between thumbnails. + * @property { number } [iOSThumbnailLineSpacing] Configure the line spacing of thumbnails. + * @property { any } [iOSThumbnailMargin] Configure the margin for thumbnails. + * @property { PDFConfiguration.BooleanType } [iOSShouldCacheThumbnails] Option to enable / disable thumbnail caching. + * @property { PDFConfiguration.EditableAnnotationTypes[] } [editableAnnotationTypes] Set containing the annotation types that should be editable. + * @property { PDFConfiguration.BooleanType } [enableAnnotationEditing] Configuration to enable / disable editing all annotations. To selectively enable editing for specific types of annotations, use ```editableAnnotationTypes```. + * @property { PDFConfiguration.BooleanType } [enableFormEditing] Enable / disable editing forms. This can also be accomplished by adding or removing the ```Widget``` annotation type from ```editableAnnotationTypes```. + * @property { PDFConfiguration.BooleanType } [androidShowAnnotationListAction] Enables the list of annotations. + * @property { PDFConfiguration.BooleanType } [iOSShouldAskForAnnotationUsername] If ```true```, asks the user to specify a custom annotation user name ("author") when creating a new annotation. + * @property { PDFConfiguration.IOSLinkAction } [iOSLinkAction] Sets the default link action for pressing on a ```LinkAnnotation```. + * @property { PDFConfiguration.IOSDrawCreateMode } [iOSDrawCreateMode] Determines whether new annotations are created when strokes end. + * @property { PDFConfiguration.BooleanType } [iOSAnnotationGroupingEnabled] If set to ```true```, you can group / ungroup annotations with the multi-select tool. + * @property { PDFConfiguration.BooleanType } [iOSNaturalDrawingAnnotationEnabled] Enables natural drawing for ink annotations. + * @property { PDFConfiguration.BooleanType } [iOSNaturalSignatureDrawingEnabled] Enables natural drawing for signatures. + * @property { PDFConfiguration.BooleanType } [iOSAnnotationEntersEditModeAfterSecondTapEnabled] Controls if a second tap to an annotation that allows inline editing enters edit mode. + * @property { PDFConfiguration.BooleanType } [iOSCreateAnnotationMenuEnabled] If set to ```true```, a long tap that ends on a page area that isn’t a text / image will show a new menu to create annotations. + * @property { number } [iOSAnnotationAnimationDuration] Overlay annotations are faded in. Set the global duration for this fade here. + * @property { number } [iOSSoundAnnotationTimeLimit] Describes the time limit for recording sound annotations, in seconds. + * @property { PDFConfiguration.IOSBookmarkSortOrder } [iOSBookmarkSortOrder] Controls how bookmarks are displayed and managed. + * @property { PDFConfiguration.BooleanType } [enableInstantComments] Enable Instant comments. + * @property { PDFConfiguration.BooleanType } [listenToServerChanges] Listen for server changes automatically. + * @property { number } [delay] The delay before syncing with the Instant server. + * @property { PDFConfiguration.BooleanType } [syncAnnotations] Indicates whether document annotations should be synced with the Instant server. + * @property { Measurements.MeasurementValueConfiguration[] } [measurementValueConfigurations] The array of ```MeasurementValueConfiguration``` objects that should be applied to the document. + */ +var PDFConfiguration = /** @class */ (function () { + function PDFConfiguration() { + } + return PDFConfiguration; +}()); +exports.PDFConfiguration = PDFConfiguration; +(function (PDFConfiguration) { + /** + * A convenience type to select Boolean options. + * @readonly + * @enum {string} BooleanType + */ + PDFConfiguration.BooleanType = { + /** + * Set the value to ```true```. + */ + TRUE: true, + /** + * Set the value to ```false```. + */ + FALSE: false, + }; + /** + * Configures the direction of page scrolling in the document view. + * @readonly + * @enum {string} ScrollDirection + */ + PDFConfiguration.ScrollDirection = { + /** + * Enable horizontal scrolling. + */ + HORIZONTAL: 'horizontal', + /** + * Enable vertical scrolling. + */ + VERTICAL: 'vertical' + }; + /** + * Configures the page scrolling mode. Note that curl mode is only available for iOS and will be ignored on Android. + * @readonly + * @enum {string} PageTransition + */ + PDFConfiguration.PageTransition = { + /** + * Transitions from one spread to another and does not stop scrolling in between two spreads (paginated). + */ + SCROLL_PER_SPREAD: 'scrollPerSpread', + /** + * Scrolls continuously. + */ + SCROLL_CONTINUOUS: 'scrollContinuous', + /** + * Page curl mode, similar to Apple Books. Not supported with variable sized PDFs. Only available on iOS. + */ + CURL: 'curl' + }; + /** + * The SignatureSavingStrategy options. + * @readonly + * @enum {string} SignatureSavingStrategy + */ + PDFConfiguration.SignatureSavingStrategy = { + /** + * Always save the signature after it is created. + */ + ALWAYS_SAVE: 'alwaysSave', + /** + * Never save the signature after it is created. + */ + NEVER_SAVE: 'neverSave', + /** + * Save the signature after it is created, if indicated by the user. + */ + SAVE_IF_SELECTED: 'saveIfSelected' + }; + /** + * The IOSDoubleTapAction options. + * @readonly + * @enum {string} IOSDoubleTapAction + */ + PDFConfiguration.IOSDoubleTapAction = { + /** + * Do not zoom on double tap. + */ + NONE: 'none', + /** + * Zoom on double tap. + */ + ZOOM: 'zoom', + /** + * Smart zoom on double tap. + */ + SMART_ZOOM: 'smartZoom' + }; + /** + * The IOSTextSelectionMode options. + * @readonly + * @enum {string} IOSTextSelectionMode + */ + PDFConfiguration.IOSTextSelectionMode = { + /** + * Selecting text in regular mode starts after a long-press and results in a selection with dragging handles. + */ + REGULAR: 'regular', + /** + * Selecting text in simple mode starts almost immediately on touch down and results in a selection with dragging handles. + */ + SIMPLE: 'simple', + /** + * Selection mode will be chosen based on input device: selecting text with finger or Apple Pencil will use regular mode, while selecting text with trackpad or mouse will use simple mode. + */ + AUTOMATIC: 'automatic' + }; + /** + * The IOSTypesShowingColorPresets options. + * @readonly + * @enum {string} IOSTypesShowingColorPresets + */ + PDFConfiguration.IOSTypesShowingColorPresets = { + NONE: 'none', + UNDEFINED: 'undefined', + ALL: 'all', + LINK: 'link', + HIGHLIGHT: 'highlight', + UNDERLINE: 'underline', + SQUIGGLY: 'squiggly', + STRIKE_OUT: 'strikeOut', + TEXT: 'text', + CARET: 'caret', + FREE_TEXT: 'freeText', + INK: 'ink', + SQUARE: 'square', + CIRCLE: 'circle', + LINE: 'line', + SIGNATURE: 'signature', + STAMP: 'stamp', + ERASER: 'eraser', + IMAGE: 'image', + WIDGET: 'widget', + FILE_ATTACHMENT: 'fileAttachment', + SOUND: 'sound', + POLYGON: 'polygon', + POLY_LINE: 'polyLine', + RICH_MEDIA: 'richMedia', + SCREEN: 'screen', + POPUP: 'popup', + WATERMARK: 'watermark', + TRAP_NET: 'trapNet', + '3D': '3D', + REDACT: 'redact', + }; + /** + * The PageMode options. + * @readonly + * @enum {string} PageMode + */ + PDFConfiguration.PageMode = { + /** + * Always show a single page. + */ + SINGLE: 'single', + /** + * Always show two pages side-by-side. + */ + DOUBLE: 'double', + /** + * Show two pages only when the view is sufficiently large and two pages can be shown without too much shrinking. + */ + AUTOMATIC: 'automatic' + }; + /** + * The SpreadFitting options. + * @readonly + * @enum {string} SpreadFitting + */ + PDFConfiguration.SpreadFitting = { + /** + * Aspect fit results in a spread view having all its pages always visible on screen. + */ + FIT: 'fit', + /** + * Aspect fills the content so that it completely covers the width of the view. + */ + FILL: 'fill', + /** + * Automatically switches between ```fit``` and ```fill```. + */ + ADAPTIVE: 'adaptive' + }; + /** + * The IOSRenderStatusViewPosition options. + * @readonly + * @enum {string} IOSRenderStatusViewPosition + */ + PDFConfiguration.IOSRenderStatusViewPosition = { + /** + * Display render status view at the top. + */ + TOP: 'top', + /** + * Display render status view at the center. + */ + CENTERED: 'centered' + }; + /** + * The IOSAllowedAppearanceModes options. + * @readonly + * @enum {string} IOSAllowedAppearanceModes + */ + PDFConfiguration.IOSAllowedAppearanceModes = { + /** + * Normal application appearance and page rendering, as configured by the host app. + */ + DEFAULT: 'default', + /** + * Renders the PDF content with a sepia tone. + */ + SEPIA: 'sepia', + /** + * Inverts the PDF page content and applies color correction. + */ + NIGHT: 'night', + /** + * All options. + */ + ALL: 'all', + }; + /** + * The UserInterfaceViewMode options. + * @readonly + * @enum {string} UserInterfaceViewMode + */ + PDFConfiguration.UserInterfaceViewMode = { + /** + * Show user interface view on touch and first/last page. + */ + AUTOMATIC: 'automatic', + /** + * Show user interface view on touch and first/last page. + */ + AUTOMATIC_BORDER_PAGES: 'automaticBorderPages', + /** + * Show user interface view on touch. + */ + AUTOMATIC_NO_FIRST_LAST_PAGE: 'automaticNoFirstLastPage', + /** + * Always show the user interface view. + */ + ALWAYS: 'always', + /** + * Always show the user interface view. + */ + ALWAYS_VISIBLE: 'alwaysVisible', + /** + * Never show the user interface view. + */ + ALWAYS_HIDDEN: 'alwaysHidden', + /** + * Never show the user interface view. + */ + NEVER: 'never', + }; + /** + * The IOSSearchMode options. + * @readonly + * @enum {string} IOSSearchMode + */ + PDFConfiguration.IOSSearchMode = { + /** + * Display search results in a modal view. + */ + MODAL: 'modal', + /** + * Display search results inline. + */ + INLINE: 'inline' + }; + /** + * The IOSAllowedMenuActions options. + * @readonly + * @enum {string} IOSAllowedMenuActions + */ + PDFConfiguration.IOSAllowedMenuActions = { + /** + * Allow no action. + */ + NONE: 'none', + /** + * Allow searching the document with selected text. + */ + SEARCH: 'search', + /** + * Allow presenting the definition for selected text. + */ + DEFINE: 'define', + /** + * Allow searching Wikipedia with selected text. + */ + WIKIPEDIA: 'wikipedia', + /** + * Allow accessibility text-to-speech. + */ + SPEAK: 'speak', + /** + * Allow all actions. + */ + ALL: 'all' + }; + /** + * The IOSSettingsOptions options. + * @readonly + * @enum {string} IOSSettingsOptions + */ + PDFConfiguration.IOSSettingsOptions = { + /** + * Shows UI to change ```ScrollDirection```. + */ + SCROLL_DIRECTION: 'scrollDirection', + /** + * Shows UI to change ```PageTransition``` (continuous or per-spread scrolling). + */ + PAGE_TRANSITION: 'pageTransition', + /** + * Shows UI to change ```AppearanceMode``` (sepia and dark rendering). + */ + APPEARANCE: 'appearance', + /** + * Shows UI to adjust screen brightness. + */ + BRIGHTNESS: 'brightness', + /** + * Shows UI to change ```PageMode``` (single or double page mode). + */ + PAGE_MODE: 'pageMode', + /** + * The default set of settings the user can adjust with ```PDFSettingsViewController```. + */ + DEFAULT: 'default', + /** + * All the settings that can be set by a ```PDFSettingsViewController```. + */ + ALL: 'all' + }; + /** + * The ShowThumbnailBar options. + * @readonly + * @enum {string} ShowThumbnailBar + */ + PDFConfiguration.ShowThumbnailBar = { + /** + * Don't show any thumbnails. + */ + NONE: 'none', + /** + * The default thumbnail bar (like Apple Books, ```ScrubberBar```) + */ + DEFAULT: 'default', + /** + * Show a floating scrubber bar (```ScrubberBar```) + */ + FLOATING: 'floating', + /** + * Show a pinned scrubber bar (```ScrubberBar```) + */ + PINNED: 'pinned', + /** + * Show scrubber bar (like Apple Books, ```ScrubberBar```) + */ + SCRUBBER_BAR: 'scrubberBar', + /** + * Show scrollable thumbnail bar (```ThumbnailBar```) + */ + SCROLLABLE: 'scrollable' + }; + /** + * The IOSScrubberBarType options. + * @readonly + * @enum {string} IOSScrubberBarType + */ + PDFConfiguration.IOSScrubberBarType = { + /** + * The default style: A scrubber bar that lays out its thumbnails along its width. + */ + HORIZONTAL: 'horizontal', + /** + * Style for a scrubber bar that lays out its thumbnails along its height and sits along the left edge of its container. + */ + VERTICAL_LEFT: 'verticalLeft', + /** + * Style for a scrubber bar that lays out its thumbnails along its height and sits along the right edge of its container view. + */ + VERTICAL_RIGHT: 'verticalRight' + }; + /** + * The IOSThumbnailGrouping options. + * @readonly + * @enum {string} IOSThumbnailGrouping + */ + PDFConfiguration.IOSThumbnailGrouping = { + /** + * Group double pages when ```PageMode.double``` is enabled. + */ + AUTOMATIC: 'automatic', + /** + * Never group double pages for thumbnails. + */ + NEVER: 'never', + /** + * Always group double pages for thumbnails. + */ + ALWAYS: 'always' + }; + /** + * The EditableAnnotationTypes options. + * @readonly + * @enum {string} EditableAnnotationTypes + */ + PDFConfiguration.EditableAnnotationTypes = { + NONE: 'none', + UNDEFINED: 'undefined', + ALL: 'all', + LINK: 'link', + HIGHLIGHT: 'highlight', + UNDERLINE: 'underline', + SQUIGGLY: 'squiggly', + STRIKE_OUT: 'strikeOut', + TEXT: 'text', + CARET: 'caret', + FREE_TEXT: 'freeText', + INK: 'ink', + SQUARE: 'square', + CIRCLE: 'circle', + LINE: 'line', + SIGNATURE: 'signature', + STAMP: 'stamp', + ERASER: 'eraser', + IMAGE: 'image', + WIDGET: 'widget', + FILE_ATTACHMENT: 'fileAttachment', + SOUND: 'sound', + POLYGON: 'polygon', + POLY_LINE: 'polyLine', + RICH_MEDIA: 'richMedia', + SCREEN: 'screen', + POPUP: 'popup', + WATERMARK: 'watermark', + TRAP_NET: 'trapNet', + '3D': '3D', + REDACT: 'redact', + }; + /** + * The IOSLinkAction options. + * @readonly + * @enum {string} IOSLinkAction + */ + PDFConfiguration.IOSLinkAction = { + /** + * Link actions are ignored. + */ + AUTOMATIC: 'none', + /** + * Link actions open an ```UIAlertView```. + */ + ALERT_VIEW: 'alertView', + /** + * Link actions directly open Safari or whichever app is set as the default browser. + */ + OPEN_SAFARI: 'openSafari', + /** + * Link actions open in an ```SFSafariViewController```, falling back on ```PDFWebViewController``` for local file URLs. + */ + INLINE_BROWSER: 'inlineBrowser', + /** + * Always uses ```PDFWebViewController```. + */ + INLINE_WEB_VIEW_CONTROLLER: 'InlineWebViewController' + }; + /** + * The IOSDrawCreateMode options. + * @readonly + * @enum {string} IOSDrawCreateMode + */ + PDFConfiguration.IOSDrawCreateMode = { + /** + * Every stroke will result in a separate ink annotation. + */ + SEPARATE: 'separate', + /** + * Strokes that have the same color/width are merged. + */ + MERGE_IF_POSSIBLE: 'mergeIfPossible' + }; + /** + * The IOSBookmarkSortOrder options. + * @readonly + * @enum {string} IOSBookmarkSortOrder + */ + PDFConfiguration.IOSBookmarkSortOrder = { + /** + * Custom sort order, based on creation, but reorderable. + */ + CUSTOM: 'custom', + /** + * Sort based on pages. + */ + PAGE_BASED: 'pageBased' + }; +})(PDFConfiguration || (exports.PDFConfiguration = PDFConfiguration = {})); diff --git a/lib/measurements/Measurements.js b/lib/measurements/Measurements.js new file mode 100644 index 00000000..6655453a --- /dev/null +++ b/lib/measurements/Measurements.js @@ -0,0 +1,146 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Measurements = void 0; +/** + * Measurement value configurations define how measurements are displayed and interpreted. + * @typedef MeasurementValueConfiguration + * @memberof Measurements + * @property {Measurements.MeasurementScale} scale - A ratio of a distance on a document page to a corresponding real world distance. + * @property {Measurements.Precision} precision - The smallest value to which measurements will be rounded. + * @property {string} [name] - Names are displayed in user interface and serve to help distinguish different scales. + * @property {boolean} [addToUndo] - Whether this new measurement configuration should be added to the undo stack (Android only). + * @property {boolean} [isSelected] - Whether this new measurement configuration should be set as selected on the UI. + */ +/** + * A ratio of a distance on a document page to a corresponding real world distance. + * @typedef MeasurementScale + * @memberof Measurements + * @property {Measurements.ScaleUnitFrom} unitFrom - The unit for the distance on a document page. + * @property {number} valueFrom - A distance on a document page. The unit of this value is given by ```unitFrom```. + * @property {Measurements.ScaleUnitTo} unitTo - The unit for the real world distance. + * @property {number} valueTo - A real world distance. The unit of this value is given by ```unitTo```. + */ +/** + * @namespace Measurements + */ +var Measurements = /** @class */ (function () { + function Measurements() { + } + return Measurements; +}()); +exports.Measurements = Measurements; +(function (Measurements) { + /** + * The MeasurementScale UnitFrom options. + * @readonly + * @enum {string} ScaleUnitFrom + */ + Measurements.ScaleUnitFrom = { + /** + * Inches (default). 1 inch is 72 PDF points. + */ + INCH: 'inch', + /** + * Millimeters + */ + MM: 'mm', + /** + * Centimeters + */ + CM: 'cm', + /** + * PDF points. A PDF point is 1/72 inch. All values in a PDF page coordinate space (e.g. an annotation’s bounding box) are specified in PDF points. + */ + PT: 'pt', + }; + /** + * The MeasurementScale UnitTo options. + * @readonly + * @enum {string} ScaleUnitTo + */ + Measurements.ScaleUnitTo = { + /** + * Inches (default) + */ + INCH: 'inch', + /** + * Millimeters + */ + MM: 'mm', + /** + * Centimeters + */ + CM: 'cm', + /** + * PDF points. You probably don’t want to use this for real world distances. + */ + PT: 'pt', + /** + * Feet + */ + FT: 'ft', + /** + * Meters + */ + M: 'm', + /** + * Yards + */ + YD: 'yd', + /** + * Kilometers + */ + KM: 'km', + /** + * Miles + */ + MI: 'mi', + }; + /** + * The MeasurementPrecision options. + * @readonly + * @enum {string} Precision + */ + Measurements.Precision = { + /** + * Round to one decimal place. For example: 3.1. + */ + ONE_DP: 'oneDP', + /** + * Round to two decimal places. For example: 3.14. + */ + TWO_DP: 'twoDP', + /** + * Round to three decimal places. For example: 3.142. + */ + THREE_DP: 'threeDP', + /** + * Round to four decimal places. For example: 3.1416. + */ + FOUR_DP: 'fourDP', + /** + * Round to whole numbers. For example: 3. + */ + WHOLE: 'whole', + /** + * Round to whole inches. + */ + WHOLE_INCH: 'whole', + /** + * Round to halves. For example: 2 1/2. + */ + HALVES_INCH: '1/2', + /** + * Round to quarters. For example: 2 3/4. Fractions will be simplified if possible. + */ + QUARTERS_INCH: '1/4', + /** + * Round to eighths. For example: 2 5/8. Fractions will be simplified if possible. + */ + EIGHTS_INCH: '1/8', + /** + * Round to sixteenths. For example: 2 9/16. Fractions will be simplified if possible. + */ + SIXTEENTHS_INCH: '1/16', + }; +})(Measurements || (exports.Measurements = Measurements = {})); diff --git a/lib/toolbar/Toolbar.js b/lib/toolbar/Toolbar.js new file mode 100644 index 00000000..2f3e9d14 --- /dev/null +++ b/lib/toolbar/Toolbar.js @@ -0,0 +1,77 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Toolbar = void 0; +/** + * A toolbar item used to display a custom button on the toolbar. + * @typedef ToolbarItem + * @memberof Toolbar + * @property {string} id - The unique identifier for the custom toolbar button. This will be used to identify the button in the ```onCustomToolbarButtonTapped``` callback. On Android the ID needs to be specified as a resource item inside your application's ```ids.xml``` file. + * @property {string} image - The image name (iOS) or resource ID (Android) for the toolbar button. Images must be included in the application bundle on iOS and specified as a drawable resource on Android. + * @property {string} [title] - The title of the toolbar button (Android only). + * @property {boolean} [showAsAction] - Whether the toolbar button should be displayed on the main toolbar (not in the drop down menu) (Android only). + */ +/** + * The toolbar buttons that should be displayed on the toolbar. + * @typedef ToolbarItems + * @memberof Toolbar + * @property {Array} buttons - An array of buttons that should be displayed on the toolbar. The buttons can be either stock toolbar buttons, custom toolbar buttons, or a combination of both. + * @property {string} [viewMode] - The viewMode for which the toolbar buttons should be set (iOS only). + * @property {string} [animated] - Whether the toolbar button change should be animated when they are set (iOS only). + */ +/** + * @namespace Toolbar + * @property { Toolbar.ToolbarItems } [leftBarButtonItems] The bar buttons to display on the left side of the navigation bar (iOS only). + * @property { Toolbar.ToolbarItems } [rightBarButtonItems] The bar buttons to display on the right side of the navigation bar (iOS only). + * @property { Toolbar.ToolbarItems } [toolbarMenuItems] The toolbar buttons to display on the toolbar (Android only). + */ +var Toolbar = /** @class */ (function () { + function Toolbar() { + } + return Toolbar; +}()); +exports.Toolbar = Toolbar; +(function (Toolbar) { + /** + * The stock toolbar buttons available to display on the PSPDFKit toolbar. + * @readonly + * @enum {string} DefaultToolbarButton + */ + Toolbar.DefaultToolbarButton = { + CLOSE_BUTTON_ITEM: 'closeButtonItem', + OUTLINE_BUTTON_ITEM: 'outlineButtonItem', + SEARCH_BUTTON_ITEM: 'searchButtonItem', + THUMBNAILS_BUTTON_ITEM: 'thumbnailsButtonItem', + DOCUMENT_EDITOR_BUTTON_ITEM: 'documentEditorButtonItem', + PRINT_BUTTON_ITEM: 'printButtonItem', + OPEN_IN_BUTTON_ITEM: 'openInButtonItem', + EMAIL_BUTTON_ITEM: 'emailButtonItem', + MESSAGE_BUTTON_ITEM: 'messageButtonItem', + ANNOTATION_BUTTON_ITEM: 'annotationButtonItem', + BOOKMARK_BUTTON_ITEM: 'bookmarkButtonItem', + BRIGHTNESS_BUTTON_ITEM: 'brightnessButtonItem', + ACTIVITY_BUTTON_ITEM: 'activityButtonItem', + SETTINGS_BUTTON_ITEM: 'settingsButtonItem', + READER_VIEW_BUTTON_ITEM: 'readerViewButtonItem', + ANNOTATION_LIST_BUTTON_ITEM: 'annotationListButtonItem', + SHARE_BUTTON_ITEM: 'shareButtonItem', + }; + /** + * The available view modes when setting the bar buttons on iOS. + * @readonly + * @enum {string} PDFViewMode + */ + Toolbar.PDFViewMode = { + /** + * Set the toolbar buttons when the Document is visible. + */ + VIEW_MODE_DOCUMENT: 'document', + /** + * Set the toolbar buttons when thumbnails are visible. + */ + VIEW_MODE_THUMBNAILS: 'thumbnails', + /** + * Set the toolbar buttons when thumbnails and page editing options are visible. + */ + VIEW_MODE_DOCUMENT_EDITOR: 'documentEditor', + }; +})(Toolbar || (exports.Toolbar = Toolbar = {})); diff --git a/package.json b/package.json index 04a761b8..2bc28961 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-pspdfkit", - "version": "2.8.1", + "version": "2.9.0", "description": "React Native PDF Library by PSPDFKit", "keywords": [ "react native", @@ -23,8 +23,10 @@ "lint": "eslint --ext .js,.jsx,.ts,.tsx ./*.js", "docs": "jsdoc -c jsdoc.json", "postdocs": "node types-scripts/fix-code-tags.js", - "generate-types": "npx -p typescript tsc", - "postgenerate-types": "node types-scripts/append.js" + "generate-types": "npx -p typescript tsc --build tsconfig-types.json", + "append": "node types-scripts/append.js", + "build": "npx -p typescript tsc --build tsconfig.json", + "build-and-generate-types": "rm -rf types lib && npm run build && npm run generate-types && npm run append" }, "peerDependencies": { "@types/react": "^18.2.28", diff --git a/react-native-pspdfkit.podspec b/react-native-pspdfkit.podspec index 9832661c..8d5fc470 100644 --- a/react-native-pspdfkit.podspec +++ b/react-native-pspdfkit.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.source = { git: "https://github.com/PSPDFKit/react-native" } s.source_files = "ios/*.{xcodeproj}", "ios/RCTPSPDFKit/*.{h,m,swift}", "ios/RCTPSPDFKit/Converters/*.{h,m,swift}" s.dependency("React") - s.dependency("PSPDFKit", "13.3.1") - s.dependency("Instant", "13.3.1") + s.dependency("PSPDFKit", "13.3.3") + s.dependency("Instant", "13.3.3") s.frameworks = "UIKit" end diff --git a/samples/Catalog/.tool-versions b/samples/Catalog/.tool-versions new file mode 100644 index 00000000..f6efb75c --- /dev/null +++ b/samples/Catalog/.tool-versions @@ -0,0 +1 @@ +nodejs 18.17.1 diff --git a/samples/Catalog/Catalog.tsx b/samples/Catalog/Catalog.tsx index 88892efa..2ed5a803 100644 --- a/samples/Catalog/Catalog.tsx +++ b/samples/Catalog/Catalog.tsx @@ -1,4 +1,4 @@ -// Copyright © 2016-2023 PSPDFKit GmbH. All rights reserved. +// Copyright © 2016-2024 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. @@ -30,6 +30,8 @@ import { SaveAs } from './examples/SaveAs'; import { SplitPDF } from './examples/SplitPDF'; import { StateChange } from './examples/StateChange'; import { ToolbarCustomization } from './examples/ToolbarCustomization'; +import { GetConfiguration } from './examples/GetConfiguration'; +import { PasswordProtectedDocument } from './examples/PasswordProtectedDocument'; import { PSPDFKit } from './helpers/PSPDFKit'; // By default, this example doesn't set a license key, but instead runs in trial mode (which is the default, @@ -101,6 +103,8 @@ class Catalog extends React.Component { name="AnnotationPresetCustomization" component={AnnotationPresetCustomization} /> + + ); diff --git a/samples/Catalog/ExamplesNavigationMenu.tsx b/samples/Catalog/ExamplesNavigationMenu.tsx index 4f595904..a8c6f317 100644 --- a/samples/Catalog/ExamplesNavigationMenu.tsx +++ b/samples/Catalog/ExamplesNavigationMenu.tsx @@ -225,6 +225,26 @@ export default [ }); }, }, + { + key: 'item21', + name: 'Get PDFConfiguration', + description: 'Get and apply PDFConfiguration to a new instance', + action: (component: any) => { + component.props.navigation.push('GetConfiguration', { + title: 'Get PDFConfiguration', + }); + }, + }, + { + key: 'item22', + name: 'Open Password Protected PDF', + description: 'Open a password protected PDF document', + action: (component: any) => { + component.props.navigation.push('PasswordProtectedDocument', { + title: 'PSPDFKitView Component', + }); + }, + }, ]; const generatePDFMenu = [ @@ -244,7 +264,7 @@ const generatePDFMenu = [ const { fileURL } = await Processor.generateBlankPDF(configuration); if (Platform.OS === 'android') { - PSPDFKit.present(fileURL, { title: 'Generate blank PDF' }); + PSPDFKit.present(fileURL, { toolbarTitle: 'Generate blank PDF' }); return; } @@ -323,7 +343,7 @@ body { if (Platform.OS === 'android') { PSPDFKit.present(fileURL, { - title: 'Generate PDF from HTML string.', + toolbarTitle: 'Generate PDF from HTML string.', }); return; } @@ -376,7 +396,7 @@ body { // Do something with new file if (Platform.OS === 'android') { - PSPDFKit.present(fileURL, { title: 'Generate PDF from URL' }); + PSPDFKit.present(fileURL, { toolbarTitle: 'Generate PDF from URL' }); return; } @@ -440,7 +460,7 @@ body { // In this example, we will open it in PSPDFKit view component from the same location where other pdf documents resides, PDFs folder in the root of the RN app if (Platform.OS === 'android') { PSPDFKit.present(fileURL, { - title: 'Generate PDF from template', + toolbarTitle: 'Generate PDF from template', }); return; } @@ -491,7 +511,7 @@ body { await Processor.generatePDFFromImages(configuration); if (Platform.OS === 'android') { - PSPDFKit.present(fileURL, { title: 'Generate PDF from images' }); + PSPDFKit.present(fileURL, { toolbarTitle: 'Generate PDF from images' }); return; } @@ -522,7 +542,7 @@ body { name: 'Generate PDF from PDF documents', description: 'Generate PDF document from existing PDF documents.', action: async (component: any) => { - let fileName = 'PDFromDocuments'; + let fileName = 'PDFFromDocuments'; let outputFile = null; // For images from assets, you'll need to provide the global path for images in iOS. // In case you took image from the camera, you can use local path, instead. @@ -557,26 +577,17 @@ body { await Processor.generatePDFFromDocuments(configuration); if (Platform.OS === 'android') { - PSPDFKit.present(fileURL, { title: 'Generate PDF from images' }); + PSPDFKit.present(fileURL, { toolbarTitle: 'Generate PDF from PDF documents' }); return; } // Do something with new file console.log('Your new file is stored in: ', fileURL); - // In this example, we will open it in PSPDFKit view component from the same location where other pdf documents resides, PDFs folder in the root of the RN app - await extractAsset( - fileURL, - documentName(fileName), - async (mainPath: any) => { - if (await fileExists(mainPath)) { - component.props.navigation.push('GeneratePDF', { - documentPath: `PDFs/${documentName(fileName)}`, - fullPath: mainPath, - title: 'Generate PDF from PDF documents', - }); - } - }, - ); + component.props.navigation.push('GeneratePDF', { + documentPath: `PDFs/${documentName(fileName)}`, + fullPath: fileURL, + title: 'Generate PDF from PDF documents', + }); } catch (e: any) { console.log(e.message, e.code); Alert.alert('PSPDFKit', e.message); diff --git a/samples/Catalog/android/app/.classpath b/samples/Catalog/android/app/.classpath index 4a04201c..bbe97e50 100644 --- a/samples/Catalog/android/app/.classpath +++ b/samples/Catalog/android/app/.classpath @@ -1,6 +1,6 @@ - + diff --git a/samples/Catalog/android/app/src/main/res/drawable/example_toolbar_icon.xml b/samples/Catalog/android/app/src/main/res/drawable/example_toolbar_icon.xml new file mode 100644 index 00000000..a81b6132 --- /dev/null +++ b/samples/Catalog/android/app/src/main/res/drawable/example_toolbar_icon.xml @@ -0,0 +1,5 @@ + + + diff --git a/samples/Catalog/android/app/src/main/res/values/ids.xml b/samples/Catalog/android/app/src/main/res/values/ids.xml new file mode 100644 index 00000000..780e7e1e --- /dev/null +++ b/samples/Catalog/android/app/src/main/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/samples/Catalog/android/app/src/main/res/values/styles.xml b/samples/Catalog/android/app/src/main/res/values/styles.xml index 6844bb88..64b3c649 100644 --- a/samples/Catalog/android/app/src/main/res/values/styles.xml +++ b/samples/Catalog/android/app/src/main/res/values/styles.xml @@ -3,10 +3,12 @@ + diff --git a/samples/Catalog/configuration/Constants.ts b/samples/Catalog/configuration/Constants.ts index c7733726..155086f1 100644 --- a/samples/Catalog/configuration/Constants.ts +++ b/samples/Catalog/configuration/Constants.ts @@ -6,6 +6,7 @@ const tiffImageName = 'PSPDFKit_Image_Example.tiff'; export const formDocumentName = 'Form_example.pdf'; const measurementsName = 'Measurements.pdf'; export const exampleDocumentName = 'PSPDFKit_Quickstart_Guide.pdf'; +export const examplePasswordDocumentName = 'PSPDFKit_Quickstart_Guide_Password.pdf'; export const exampleImage = 'PSPDFKit_Image_Example.jpg'; export const exampleImagePath = @@ -24,6 +25,11 @@ export const exampleDocumentPath = ? 'PDFs/' + exampleDocumentName : 'file:///android_asset/' + exampleDocumentName; +export const examplePasswordDocumentPath = + Platform.OS === 'ios' + ? 'PDFs/' + examplePasswordDocumentName + : 'file:///android_asset/' + examplePasswordDocumentName; + export const tiffImagePath = Platform.OS === 'ios' ? 'PDFs/' + tiffImageName diff --git a/samples/Catalog/examples/AnnotationPresetCustomization.tsx b/samples/Catalog/examples/AnnotationPresetCustomization.tsx index a4d01f4e..71d45ff3 100644 --- a/samples/Catalog/examples/AnnotationPresetCustomization.tsx +++ b/samples/Catalog/examples/AnnotationPresetCustomization.tsx @@ -24,10 +24,10 @@ export class AnnotationPresetCustomization extends BaseExampleAutoHidingHeaderCo ref={this.pdfRef} document={exampleDocumentPath} configuration={{ - allowToolbarTitleChange: false, + iOSAllowToolbarTitleChange: false, toolbarTitle: 'My Awesome Report', - backgroundColor: processColor('lightgrey'), - useParentNavigationBar: false, + iOSBackgroundColor: processColor('lightgrey'), + iOSUseParentNavigationBar: false, }} annotationPresets={{ inkPen: { diff --git a/samples/Catalog/examples/AnnotationProcessing.tsx b/samples/Catalog/examples/AnnotationProcessing.tsx index cb08d002..7603e766 100644 --- a/samples/Catalog/examples/AnnotationProcessing.tsx +++ b/samples/Catalog/examples/AnnotationProcessing.tsx @@ -29,7 +29,7 @@ export class AnnotationProcessing extends BaseExampleAutoHidingHeaderComponent { document={writableDocumentPath} disableAutomaticSaving={true} configuration={{ - backgroundColor: processColor('lightgrey'), + iOSBackgroundColor: processColor('lightgrey'), }} style={styles.pdfColor} /> diff --git a/samples/Catalog/examples/CustomFontPicker.tsx b/samples/Catalog/examples/CustomFontPicker.tsx index 984887e2..dcad2bb6 100644 --- a/samples/Catalog/examples/CustomFontPicker.tsx +++ b/samples/Catalog/examples/CustomFontPicker.tsx @@ -23,9 +23,9 @@ export class CustomFontPicker extends BaseExampleAutoHidingHeaderComponent { document={exampleDocumentPath} ref={this.pdfRef} configuration={{ - backgroundColor: processColor('lightgrey'), + iOSBackgroundColor: processColor('lightgrey'), showThumbnailBar: 'scrubberBar', - useParentNavigationBar: false, + iOSUseParentNavigationBar: false, }} availableFontNames={[ 'Arial', diff --git a/samples/Catalog/examples/EventListeners.tsx b/samples/Catalog/examples/EventListeners.tsx index 5882464b..5fc19d7b 100644 --- a/samples/Catalog/examples/EventListeners.tsx +++ b/samples/Catalog/examples/EventListeners.tsx @@ -23,7 +23,7 @@ export class EventListeners extends BaseExampleAutoHidingHeaderComponent { document={exampleDocumentPath} ref={this.pdfRef} configuration={{ - backgroundColor: processColor('lightgrey'), + iOSBackgroundColor: processColor('lightgrey'), }} style={styles.pdfColor} // Event Listeners @@ -61,6 +61,13 @@ export class EventListeners extends BaseExampleAutoHidingHeaderComponent { Alert.alert('PSPDFKit', 'Document Saved!'); } }} + onDocumentLoaded={(event: { error: any }) => { + if (event.error) { + Alert.alert('PSPDFKit', event.error); + } else { + Alert.alert('PSPDFKit', 'Document Loaded!'); + } + }} /> ); diff --git a/samples/Catalog/examples/GeneratePDF.tsx b/samples/Catalog/examples/GeneratePDF.tsx index 3f82c911..acd68ac8 100644 --- a/samples/Catalog/examples/GeneratePDF.tsx +++ b/samples/Catalog/examples/GeneratePDF.tsx @@ -23,7 +23,7 @@ export class GeneratePDF extends BaseExampleAutoHidingHeaderComponent { ref={this.pdfRef} document={fullPath} configuration={{ - backgroundColor: processColor('lightgrey'), + iOSBackgroundColor: processColor('lightgrey'), }} style={styles.pdfColor} /> diff --git a/samples/Catalog/examples/GetConfiguration.tsx b/samples/Catalog/examples/GetConfiguration.tsx new file mode 100644 index 00000000..b4bed0ee --- /dev/null +++ b/samples/Catalog/examples/GetConfiguration.tsx @@ -0,0 +1,82 @@ +import React from 'react'; +import { Alert, Button, processColor, View } from 'react-native'; +import PSPDFKitView, { PDFConfiguration } from 'react-native-pspdfkit'; + +import { + pspdfkitColor, + exampleDocumentPath, +} from '../configuration/Constants'; +import { BaseExampleAutoHidingHeaderComponent } from '../helpers/BaseExampleAutoHidingHeaderComponent'; +import { PSPDFKit } from '../helpers/PSPDFKit'; + +export class GetConfiguration extends BaseExampleAutoHidingHeaderComponent { + pdfRef: React.RefObject; + + constructor(props: any) { + super(props); + this.pdfRef = React.createRef(); + } + + override render() { + return ( + + + + +