Skip to content

Add more Android configuration options #345

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions android/src/main/java/com/pspdfkit/react/ConfigurationAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
import com.pspdfkit.configuration.page.PageScrollMode;
import com.pspdfkit.configuration.sharing.ShareFeatures;

import java.util.EnumSet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -84,6 +82,8 @@ public class ConfigurationAdapter {
private static final String AUTOSAVE_DISABLED = "disableAutomaticSaving";
private static final String ANNOTATION_EDITING_ENABLED = "enableAnnotationEditing";
private static final String EDITABLE_ANNOTATION_TYPES = "editableAnnotationTypes";
private static final String SHOW_SETTINGS_MENU = "showSettingsMenu";
private static final String TOOLBAR_TITLE = "toolbarTitle";

private final PdfActivityConfiguration.Builder configuration;

Expand Down Expand Up @@ -174,6 +174,12 @@ public ConfigurationAdapter(@NonNull Context context, ReadableMap configuration)
if (configuration.hasKey(EDITABLE_ANNOTATION_TYPES)) {
configureEditableAnnotationTypes(configuration.getArray(EDITABLE_ANNOTATION_TYPES));
}
if (configuration.hasKey(SHOW_SETTINGS_MENU)) {
configureSettingsMenuShown(configuration.getBoolean(SHOW_SETTINGS_MENU));
}
if (configuration.hasKey(TOOLBAR_TITLE)) {
configureToolbarTitle(configuration.getString(TOOLBAR_TITLE));
}
}
}

Expand Down Expand Up @@ -396,6 +402,18 @@ private void configureEditableAnnotationTypes(@Nullable final ReadableArray edit
configuration.editableAnnotationTypes(parsedTypes);
}

private void configureSettingsMenuShown(final boolean settingsMenuShown) {
if (settingsMenuShown) {
configuration.showSettingsMenu();
} else {
configuration.hideSettingsMenu();
}
}

private void configureToolbarTitle(@Nullable final String customTitle) {
configuration.title(customTitle);
}

public PdfActivityConfiguration build() {
return configuration.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ public void setMenuItemGrouping(PdfView view, @NonNull ReadableArray menuItemGro
view.setMenuItemGroupingRule(groupingRule);
}

@ReactProp(name = "showNavigationButtonInToolbar")
public void setShowNavigationButtonInToolbar(@NonNull final PdfView view, final boolean showNavigationButtonInToolbar) {
view.setShowNavigationButtonInToolbar(showNavigationButtonInToolbar);
}

@Nullable
@Override
public Map getExportedCustomDirectEventTypeConstants() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.pspdfkit.react.events;

import androidx.annotation.IdRes;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;

/**
* Event sent by the {@link com.pspdfkit.views.PdfView} when navigation button was clicked.
*/
public class PdfViewNavigationButtonClickedEvent extends Event<PdfViewNavigationButtonClickedEvent> {

public static final String EVENT_NAME = "pdfViewNavgigationButtonClicked";

public PdfViewNavigationButtonClickedEvent(@IdRes int viewId) {
super(viewId);
}

@Override
public String getEventName() {
return EVENT_NAME;
}

@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
WritableMap eventData = Arguments.createMap();
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData);
}
}

This file was deleted.

67 changes: 47 additions & 20 deletions android/src/main/java/com/pspdfkit/views/PdfView.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
import com.pspdfkit.react.events.PdfViewDocumentLoadFailedEvent;
import com.pspdfkit.react.events.PdfViewDocumentSaveFailedEvent;
import com.pspdfkit.react.events.PdfViewDocumentSavedEvent;
import com.pspdfkit.react.events.PdfViewNavigationButtonClickedEvent;
import com.pspdfkit.react.events.PdfViewStateChangedEvent;
import com.pspdfkit.react.helper.DocumentJsonDataProvider;
import com.pspdfkit.ui.DocumentDescriptor;
import com.pspdfkit.ui.PdfFragment;
import com.pspdfkit.ui.PdfUi;
import com.pspdfkit.ui.PdfUiFragment;
import com.pspdfkit.ui.PdfUiFragmentBuilder;
import com.pspdfkit.ui.toolbar.grouping.MenuItemGroupingRule;
Expand All @@ -50,6 +50,7 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -97,7 +98,10 @@ public class PdfView extends FrameLayout {

@Nullable
private PdfUiFragment fragment;
private BehaviorSubject<PdfUiFragment> pdfUiFragmentGetter = BehaviorSubject.create();

/** We wrap the fragment in a list so we can have a state that encapsulates no element being set. */
@NonNull
private final BehaviorSubject<List<PdfUiFragment>> pdfUiFragmentGetter = BehaviorSubject.createDefault(Collections.emptyList());

/** An internal id we generate so we can track if fragments found belong to this specific PdfView instance. */
private int internalId;
Expand Down Expand Up @@ -219,6 +223,14 @@ public void setMenuItemGroupingRule(@NonNull MenuItemGroupingRule groupingRule)
pdfViewModeController.setMenuItemGroupingRule(groupingRule);
}

public void setShowNavigationButtonInToolbar(final boolean showNavigationButtonInToolbar) {
pendingFragmentActions.add(getCurrentPdfUiFragment()
.observeOn(Schedulers.io())
.subscribe(pdfUiFragment -> {
((ReactPdfUiFragment) pdfUiFragment).setShowNavigationButtonInToolbar(showNavigationButtonInToolbar);
}));
}

private void setupFragment() {
if (fragmentTag != null && configuration != null && document != null) {
PdfUiFragment pdfFragment = (PdfUiFragment) fragmentManager.findFragmentByTag(fragmentTag);
Expand All @@ -235,7 +247,7 @@ private void setupFragment() {
if (pdfFragment == null) {
pdfFragment = PdfUiFragmentBuilder.fromDocumentDescriptor(getContext(), DocumentDescriptor.fromDocument(document))
.configuration(configuration)
.fragmentClass(ConfigurationChangeReportingPdfUiFragment.class)
.fragmentClass(ReactPdfUiFragment.class)
.build();
// We put our internal id so we can track if this fragment belongs to us, used to handle orphaned fragments after hot reloads.
pdfFragment.getArguments().putInt(ARG_ROOT_ID, internalId);
Expand All @@ -249,7 +261,7 @@ private void setupFragment() {
// The document changed create a new PdfFragment.
pdfFragment = PdfUiFragmentBuilder.fromDocumentDescriptor(getContext(), DocumentDescriptor.fromDocument(document))
.configuration(configuration)
.fragmentClass(ConfigurationChangeReportingPdfUiFragment.class)
.fragmentClass(ReactPdfUiFragment.class)
.build();
prepareFragment(pdfFragment);
} else if (fragmentView != null && fragmentView.getParent() != this) {
Expand All @@ -266,7 +278,7 @@ private void setupFragment() {
}

fragment = pdfFragment;
pdfUiFragmentGetter.onNext(fragment);
pdfUiFragmentGetter.onNext(Collections.singletonList(pdfFragment));
}
}

Expand All @@ -279,9 +291,17 @@ private void prepareFragment(final PdfUiFragment pdfUiFragment) {

pdfUiFragment.setOnContextualToolbarLifecycleListener(pdfViewModeController);
pdfUiFragment.getPSPDFKitViews().getFormEditingBarView().addOnFormEditingBarLifecycleListener(pdfViewModeController);
((ConfigurationChangeReportingPdfUiFragment) pdfUiFragment).setOnConfigurationChangedListener(() -> {
// If the configuration was changed from the UI a new fragment will be created, reattach our listeners.
preparePdfFragment(pdfUiFragment.getPdfFragment());
((ReactPdfUiFragment) pdfUiFragment).setReactPdfUiFragmentListener(new ReactPdfUiFragment.ReactPdfUiFragmentListener() {
@Override
public void onConfigurationChanged(@NonNull PdfUiFragment pdfUiFragment) {
// If the configuration was changed from the UI a new fragment will be created, reattach our listeners.
preparePdfFragment(pdfUiFragment.getPdfFragment());
}

@Override
public void onNavigationButtonClicked(@NonNull PdfUiFragment pdfUiFragment) {
eventDispatcher.dispatchEvent(new PdfViewNavigationButtonClickedEvent(getId()));
}
});

// After attaching the PdfUiFragment we can access the PdfFragment.
Expand Down Expand Up @@ -315,14 +335,14 @@ public void removeFragment(boolean makeInactive) {
// Clear everything.
isActive = false;
document = null;

pendingFragmentActions.dispose();
pendingFragmentActions = new CompositeDisposable();
}

fragment = null;

pdfUiFragmentGetter.onComplete();
pdfUiFragmentGetter = BehaviorSubject.create();
pendingFragmentActions.dispose();
pendingFragmentActions = new CompositeDisposable();
pdfUiFragmentGetter.onNext(Collections.emptyList());
}

void manuallyLayoutChildren() {
Expand Down Expand Up @@ -622,9 +642,15 @@ public Maybe<Boolean> setFormFieldValue(@NonNull String formElementName, @NonNul

/** Returns the {@link PdfFragment} hosted in the current {@link PdfUiFragment}. */
private Observable<PdfFragment> getCurrentPdfFragment() {
return getPdfFragment()
.take(1);
}

/** Returns the {@link PdfUiFragment}. */
private Observable<PdfUiFragment> getCurrentPdfUiFragment() {
return pdfUiFragmentGetter
.filter(pdfUiFragment -> pdfUiFragment.getPdfFragment() != null)
.map(PdfUiFragment::getPdfFragment)
.filter(pdfUiFragments -> !pdfUiFragments.isEmpty())
.map(pdfUiFragments -> pdfUiFragments.get(0))
.take(1);
}

Expand All @@ -642,24 +668,25 @@ public Maybe<PdfFragment> getActivePdfFragment() {
*/
public Observable<PdfFragment> getPdfFragment() {
return pdfUiFragmentGetter
.filter(pdfUiFragments -> !pdfUiFragments.isEmpty())
.map(pdfUiFragments -> pdfUiFragments.get(0))
.filter(pdfUiFragment -> pdfUiFragment.getPdfFragment() != null)
.map(PdfUiFragment::getPdfFragment);
}

/** Returns the current fragment if it is set. */
public Maybe<PdfFragment> getFragment() {
return pdfUiFragmentGetter.firstElement().map(PdfUi::getPdfFragment);
}

/** Returns the event registration map for the default events emitted by the {@link PdfView}. */
public static Map<String, Map<String, String>> createDefaultEventRegistrationMap() {
return MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"),
Map<String , Map<String, String>> map = MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"),
PdfViewDocumentSavedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaved"),
PdfViewAnnotationTappedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationTapped"),
PdfViewAnnotationChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationsChanged"),
PdfViewDataReturnedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDataReturned"),
PdfViewDocumentSaveFailedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaveFailed"),
PdfViewDocumentLoadFailedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentLoadFailed")
);

map.put(PdfViewNavigationButtonClickedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onNavigationButtonClicked"));

return map;
}
}
67 changes: 67 additions & 0 deletions android/src/main/java/com/pspdfkit/views/ReactPdfUiFragment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.pspdfkit.views;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;

import com.pspdfkit.configuration.activity.PdfActivityConfiguration;
import com.pspdfkit.react.R;
import com.pspdfkit.ui.PdfUiFragment;

/**
* This {@link PdfUiFragment} provides additional callbacks to improve integration into react native.
* <p/>
* <ul>
* <li>A callback when the configuration was changed.</li>
* <li>A method to show and hide the navigation button in the toolbar, as well as a callback for when it is clicked.</li>
* </ul>
*/
public class ReactPdfUiFragment extends PdfUiFragment {

@Nullable private ReactPdfUiFragmentListener reactPdfUiFragmentListener;

void setReactPdfUiFragmentListener(@Nullable ReactPdfUiFragmentListener listener) {
this.reactPdfUiFragmentListener = listener;
}

@Override
public void performApplyConfiguration(@NonNull PdfActivityConfiguration configuration) {
super.performApplyConfiguration(configuration);

if (this.reactPdfUiFragmentListener != null) {
reactPdfUiFragmentListener.onConfigurationChanged(this);
}
}


/** When set to true will add a navigation arrow to the toolbar. */
void setShowNavigationButtonInToolbar(final boolean showNavigationButtonInToolbar) {
if (getView() == null) {
return;
}
Toolbar toolbar = getView().findViewById(R.id.pspdf__toolbar_main);
if (showNavigationButtonInToolbar) {
toolbar.setNavigationIcon(R.drawable.pspdf__ic_navigation_arrow);
toolbar.setNavigationOnClickListener(v -> {
if (reactPdfUiFragmentListener != null) {
reactPdfUiFragmentListener.onNavigationButtonClicked(this);
}
});
} else {
toolbar.setNavigationIcon(null);
toolbar.setNavigationOnClickListener(null);
}
}

/**
* Listener that notifies of actions taken directly in the PdfUiFragment.
*/
public interface ReactPdfUiFragmentListener {

/** Called when the configuration changed, reset your {@link com.pspdfkit.ui.PdfFragment} listeners in here. */
void onConfigurationChanged(@NonNull PdfUiFragment pdfUiFragment);

/** Called when the back navigation button was clicked. */
void onNavigationButtonClicked(@NonNull PdfUiFragment pdfUiFragment);
}
}
9 changes: 9 additions & 0 deletions android/src/main/res/drawable/pspdf__ic_navigation_arrow.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
Loading