Skip to content

Commit 6841c48

Browse files
author
Reinhard Hafenscher
authored
Merge pull request #345 from PSPDFKit/reinhard/344-additional-configuration
Add more Android configuration options
2 parents 3ab0daa + b90d3d7 commit 6841c48

13 files changed

+210
-67
lines changed

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
import com.pspdfkit.configuration.page.PageScrollMode;
3333
import com.pspdfkit.configuration.sharing.ShareFeatures;
3434

35-
import java.util.EnumSet;
36-
3735
import java.util.ArrayList;
3836
import java.util.Collections;
3937
import java.util.List;
@@ -84,6 +82,8 @@ public class ConfigurationAdapter {
8482
private static final String AUTOSAVE_DISABLED = "disableAutomaticSaving";
8583
private static final String ANNOTATION_EDITING_ENABLED = "enableAnnotationEditing";
8684
private static final String EDITABLE_ANNOTATION_TYPES = "editableAnnotationTypes";
85+
private static final String SHOW_SETTINGS_MENU = "showSettingsMenu";
86+
private static final String TOOLBAR_TITLE = "toolbarTitle";
8787

8888
private final PdfActivityConfiguration.Builder configuration;
8989

@@ -174,6 +174,12 @@ public ConfigurationAdapter(@NonNull Context context, ReadableMap configuration)
174174
if (configuration.hasKey(EDITABLE_ANNOTATION_TYPES)) {
175175
configureEditableAnnotationTypes(configuration.getArray(EDITABLE_ANNOTATION_TYPES));
176176
}
177+
if (configuration.hasKey(SHOW_SETTINGS_MENU)) {
178+
configureSettingsMenuShown(configuration.getBoolean(SHOW_SETTINGS_MENU));
179+
}
180+
if (configuration.hasKey(TOOLBAR_TITLE)) {
181+
configureToolbarTitle(configuration.getString(TOOLBAR_TITLE));
182+
}
177183
}
178184
}
179185

@@ -396,6 +402,18 @@ private void configureEditableAnnotationTypes(@Nullable final ReadableArray edit
396402
configuration.editableAnnotationTypes(parsedTypes);
397403
}
398404

405+
private void configureSettingsMenuShown(final boolean settingsMenuShown) {
406+
if (settingsMenuShown) {
407+
configuration.showSettingsMenu();
408+
} else {
409+
configuration.hideSettingsMenu();
410+
}
411+
}
412+
413+
private void configureToolbarTitle(@Nullable final String customTitle) {
414+
configuration.title(customTitle);
415+
}
416+
399417
public PdfActivityConfiguration build() {
400418
return configuration.build();
401419
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ public void setMenuItemGrouping(PdfView view, @NonNull ReadableArray menuItemGro
148148
view.setMenuItemGroupingRule(groupingRule);
149149
}
150150

151+
@ReactProp(name = "showNavigationButtonInToolbar")
152+
public void setShowNavigationButtonInToolbar(@NonNull final PdfView view, final boolean showNavigationButtonInToolbar) {
153+
view.setShowNavigationButtonInToolbar(showNavigationButtonInToolbar);
154+
}
155+
151156
@Nullable
152157
@Override
153158
public Map getExportedCustomDirectEventTypeConstants() {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.pspdfkit.react.events;
2+
3+
import androidx.annotation.IdRes;
4+
5+
import com.facebook.react.bridge.Arguments;
6+
import com.facebook.react.bridge.WritableMap;
7+
import com.facebook.react.uimanager.events.Event;
8+
import com.facebook.react.uimanager.events.RCTEventEmitter;
9+
10+
/**
11+
* Event sent by the {@link com.pspdfkit.views.PdfView} when navigation button was clicked.
12+
*/
13+
public class PdfViewNavigationButtonClickedEvent extends Event<PdfViewNavigationButtonClickedEvent> {
14+
15+
public static final String EVENT_NAME = "pdfViewNavgigationButtonClicked";
16+
17+
public PdfViewNavigationButtonClickedEvent(@IdRes int viewId) {
18+
super(viewId);
19+
}
20+
21+
@Override
22+
public String getEventName() {
23+
return EVENT_NAME;
24+
}
25+
26+
@Override
27+
public void dispatch(RCTEventEmitter rctEventEmitter) {
28+
WritableMap eventData = Arguments.createMap();
29+
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData);
30+
}
31+
}

android/src/main/java/com/pspdfkit/views/ConfigurationChangeReportingPdfUiFragment.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

android/src/main/java/com/pspdfkit/views/PdfView.java

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
import com.pspdfkit.react.events.PdfViewDocumentLoadFailedEvent;
3535
import com.pspdfkit.react.events.PdfViewDocumentSaveFailedEvent;
3636
import com.pspdfkit.react.events.PdfViewDocumentSavedEvent;
37+
import com.pspdfkit.react.events.PdfViewNavigationButtonClickedEvent;
3738
import com.pspdfkit.react.events.PdfViewStateChangedEvent;
3839
import com.pspdfkit.react.helper.DocumentJsonDataProvider;
3940
import com.pspdfkit.ui.DocumentDescriptor;
4041
import com.pspdfkit.ui.PdfFragment;
41-
import com.pspdfkit.ui.PdfUi;
4242
import com.pspdfkit.ui.PdfUiFragment;
4343
import com.pspdfkit.ui.PdfUiFragmentBuilder;
4444
import com.pspdfkit.ui.toolbar.grouping.MenuItemGroupingRule;
@@ -50,6 +50,7 @@
5050
import java.io.ByteArrayOutputStream;
5151
import java.io.File;
5252
import java.util.ArrayList;
53+
import java.util.Collections;
5354
import java.util.EnumSet;
5455
import java.util.List;
5556
import java.util.Map;
@@ -97,7 +98,10 @@ public class PdfView extends FrameLayout {
9798

9899
@Nullable
99100
private PdfUiFragment fragment;
100-
private BehaviorSubject<PdfUiFragment> pdfUiFragmentGetter = BehaviorSubject.create();
101+
102+
/** We wrap the fragment in a list so we can have a state that encapsulates no element being set. */
103+
@NonNull
104+
private final BehaviorSubject<List<PdfUiFragment>> pdfUiFragmentGetter = BehaviorSubject.createDefault(Collections.emptyList());
101105

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

226+
public void setShowNavigationButtonInToolbar(final boolean showNavigationButtonInToolbar) {
227+
pendingFragmentActions.add(getCurrentPdfUiFragment()
228+
.observeOn(Schedulers.io())
229+
.subscribe(pdfUiFragment -> {
230+
((ReactPdfUiFragment) pdfUiFragment).setShowNavigationButtonInToolbar(showNavigationButtonInToolbar);
231+
}));
232+
}
233+
222234
private void setupFragment() {
223235
if (fragmentTag != null && configuration != null && document != null) {
224236
PdfUiFragment pdfFragment = (PdfUiFragment) fragmentManager.findFragmentByTag(fragmentTag);
@@ -235,7 +247,7 @@ private void setupFragment() {
235247
if (pdfFragment == null) {
236248
pdfFragment = PdfUiFragmentBuilder.fromDocumentDescriptor(getContext(), DocumentDescriptor.fromDocument(document))
237249
.configuration(configuration)
238-
.fragmentClass(ConfigurationChangeReportingPdfUiFragment.class)
250+
.fragmentClass(ReactPdfUiFragment.class)
239251
.build();
240252
// We put our internal id so we can track if this fragment belongs to us, used to handle orphaned fragments after hot reloads.
241253
pdfFragment.getArguments().putInt(ARG_ROOT_ID, internalId);
@@ -249,7 +261,7 @@ private void setupFragment() {
249261
// The document changed create a new PdfFragment.
250262
pdfFragment = PdfUiFragmentBuilder.fromDocumentDescriptor(getContext(), DocumentDescriptor.fromDocument(document))
251263
.configuration(configuration)
252-
.fragmentClass(ConfigurationChangeReportingPdfUiFragment.class)
264+
.fragmentClass(ReactPdfUiFragment.class)
253265
.build();
254266
prepareFragment(pdfFragment);
255267
} else if (fragmentView != null && fragmentView.getParent() != this) {
@@ -266,7 +278,7 @@ private void setupFragment() {
266278
}
267279

268280
fragment = pdfFragment;
269-
pdfUiFragmentGetter.onNext(fragment);
281+
pdfUiFragmentGetter.onNext(Collections.singletonList(pdfFragment));
270282
}
271283
}
272284

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

280292
pdfUiFragment.setOnContextualToolbarLifecycleListener(pdfViewModeController);
281293
pdfUiFragment.getPSPDFKitViews().getFormEditingBarView().addOnFormEditingBarLifecycleListener(pdfViewModeController);
282-
((ConfigurationChangeReportingPdfUiFragment) pdfUiFragment).setOnConfigurationChangedListener(() -> {
283-
// If the configuration was changed from the UI a new fragment will be created, reattach our listeners.
284-
preparePdfFragment(pdfUiFragment.getPdfFragment());
294+
((ReactPdfUiFragment) pdfUiFragment).setReactPdfUiFragmentListener(new ReactPdfUiFragment.ReactPdfUiFragmentListener() {
295+
@Override
296+
public void onConfigurationChanged(@NonNull PdfUiFragment pdfUiFragment) {
297+
// If the configuration was changed from the UI a new fragment will be created, reattach our listeners.
298+
preparePdfFragment(pdfUiFragment.getPdfFragment());
299+
}
300+
301+
@Override
302+
public void onNavigationButtonClicked(@NonNull PdfUiFragment pdfUiFragment) {
303+
eventDispatcher.dispatchEvent(new PdfViewNavigationButtonClickedEvent(getId()));
304+
}
285305
});
286306

287307
// After attaching the PdfUiFragment we can access the PdfFragment.
@@ -315,14 +335,14 @@ public void removeFragment(boolean makeInactive) {
315335
// Clear everything.
316336
isActive = false;
317337
document = null;
338+
339+
pendingFragmentActions.dispose();
340+
pendingFragmentActions = new CompositeDisposable();
318341
}
319342

320343
fragment = null;
321344

322-
pdfUiFragmentGetter.onComplete();
323-
pdfUiFragmentGetter = BehaviorSubject.create();
324-
pendingFragmentActions.dispose();
325-
pendingFragmentActions = new CompositeDisposable();
345+
pdfUiFragmentGetter.onNext(Collections.emptyList());
326346
}
327347

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

623643
/** Returns the {@link PdfFragment} hosted in the current {@link PdfUiFragment}. */
624644
private Observable<PdfFragment> getCurrentPdfFragment() {
645+
return getPdfFragment()
646+
.take(1);
647+
}
648+
649+
/** Returns the {@link PdfUiFragment}. */
650+
private Observable<PdfUiFragment> getCurrentPdfUiFragment() {
625651
return pdfUiFragmentGetter
626-
.filter(pdfUiFragment -> pdfUiFragment.getPdfFragment() != null)
627-
.map(PdfUiFragment::getPdfFragment)
652+
.filter(pdfUiFragments -> !pdfUiFragments.isEmpty())
653+
.map(pdfUiFragments -> pdfUiFragments.get(0))
628654
.take(1);
629655
}
630656

@@ -642,24 +668,25 @@ public Maybe<PdfFragment> getActivePdfFragment() {
642668
*/
643669
public Observable<PdfFragment> getPdfFragment() {
644670
return pdfUiFragmentGetter
671+
.filter(pdfUiFragments -> !pdfUiFragments.isEmpty())
672+
.map(pdfUiFragments -> pdfUiFragments.get(0))
645673
.filter(pdfUiFragment -> pdfUiFragment.getPdfFragment() != null)
646674
.map(PdfUiFragment::getPdfFragment);
647675
}
648676

649-
/** Returns the current fragment if it is set. */
650-
public Maybe<PdfFragment> getFragment() {
651-
return pdfUiFragmentGetter.firstElement().map(PdfUi::getPdfFragment);
652-
}
653-
654677
/** Returns the event registration map for the default events emitted by the {@link PdfView}. */
655678
public static Map<String, Map<String, String>> createDefaultEventRegistrationMap() {
656-
return MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"),
679+
Map<String , Map<String, String>> map = MapBuilder.of(PdfViewStateChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStateChanged"),
657680
PdfViewDocumentSavedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaved"),
658681
PdfViewAnnotationTappedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationTapped"),
659682
PdfViewAnnotationChangedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onAnnotationsChanged"),
660683
PdfViewDataReturnedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDataReturned"),
661684
PdfViewDocumentSaveFailedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentSaveFailed"),
662685
PdfViewDocumentLoadFailedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDocumentLoadFailed")
663686
);
687+
688+
map.put(PdfViewNavigationButtonClickedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onNavigationButtonClicked"));
689+
690+
return map;
664691
}
665692
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.pspdfkit.views;
2+
3+
import androidx.annotation.NonNull;
4+
import androidx.annotation.Nullable;
5+
import androidx.appcompat.widget.Toolbar;
6+
7+
import com.pspdfkit.configuration.activity.PdfActivityConfiguration;
8+
import com.pspdfkit.react.R;
9+
import com.pspdfkit.ui.PdfUiFragment;
10+
11+
/**
12+
* This {@link PdfUiFragment} provides additional callbacks to improve integration into react native.
13+
* <p/>
14+
* <ul>
15+
* <li>A callback when the configuration was changed.</li>
16+
* <li>A method to show and hide the navigation button in the toolbar, as well as a callback for when it is clicked.</li>
17+
* </ul>
18+
*/
19+
public class ReactPdfUiFragment extends PdfUiFragment {
20+
21+
@Nullable private ReactPdfUiFragmentListener reactPdfUiFragmentListener;
22+
23+
void setReactPdfUiFragmentListener(@Nullable ReactPdfUiFragmentListener listener) {
24+
this.reactPdfUiFragmentListener = listener;
25+
}
26+
27+
@Override
28+
public void performApplyConfiguration(@NonNull PdfActivityConfiguration configuration) {
29+
super.performApplyConfiguration(configuration);
30+
31+
if (this.reactPdfUiFragmentListener != null) {
32+
reactPdfUiFragmentListener.onConfigurationChanged(this);
33+
}
34+
}
35+
36+
37+
/** When set to true will add a navigation arrow to the toolbar. */
38+
void setShowNavigationButtonInToolbar(final boolean showNavigationButtonInToolbar) {
39+
if (getView() == null) {
40+
return;
41+
}
42+
Toolbar toolbar = getView().findViewById(R.id.pspdf__toolbar_main);
43+
if (showNavigationButtonInToolbar) {
44+
toolbar.setNavigationIcon(R.drawable.pspdf__ic_navigation_arrow);
45+
toolbar.setNavigationOnClickListener(v -> {
46+
if (reactPdfUiFragmentListener != null) {
47+
reactPdfUiFragmentListener.onNavigationButtonClicked(this);
48+
}
49+
});
50+
} else {
51+
toolbar.setNavigationIcon(null);
52+
toolbar.setNavigationOnClickListener(null);
53+
}
54+
}
55+
56+
/**
57+
* Listener that notifies of actions taken directly in the PdfUiFragment.
58+
*/
59+
public interface ReactPdfUiFragmentListener {
60+
61+
/** Called when the configuration changed, reset your {@link com.pspdfkit.ui.PdfFragment} listeners in here. */
62+
void onConfigurationChanged(@NonNull PdfUiFragment pdfUiFragment);
63+
64+
/** Called when the back navigation button was clicked. */
65+
void onNavigationButtonClicked(@NonNull PdfUiFragment pdfUiFragment);
66+
}
67+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24.0"
5+
android:viewportHeight="24.0">
6+
<path
7+
android:fillColor="#FFFFFF"
8+
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
9+
</vector>

0 commit comments

Comments
 (0)