diff --git a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java index 5c20f28b..1458f988 100644 --- a/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java +++ b/android/src/main/java/com/pspdfkit/react/ReactPdfViewManager.java @@ -14,13 +14,7 @@ import com.facebook.react.uimanager.annotations.ReactProp; import com.pspdfkit.annotations.Annotation; import com.pspdfkit.preferences.PSPDFKitPreferences; -import com.pspdfkit.react.events.PdfViewAnnotationChangedEvent; -import com.pspdfkit.react.events.PdfViewAnnotationTappedEvent; import com.pspdfkit.react.events.PdfViewDataReturnedEvent; -import com.pspdfkit.react.events.PdfViewDocumentLoadFailedEvent; -import com.pspdfkit.react.events.PdfViewDocumentSaveFailedEvent; -import com.pspdfkit.react.events.PdfViewDocumentSavedEvent; -import com.pspdfkit.react.events.PdfViewStateChangedEvent; import com.pspdfkit.react.menu.ReactGroupingRule; import com.pspdfkit.views.PdfView; @@ -154,10 +148,20 @@ public void setShowNavigationButtonInToolbar(@NonNull final PdfView view, final } @ReactProp(name= "hideDefaultToolbar") - public void setHideDefaultToolbar(@NonNull final PdfView view,final boolean hideDefaultToolbar) { + public void setHideDefaultToolbar(@NonNull final PdfView view, final boolean hideDefaultToolbar) { view.setHideDefaultToolbar(hideDefaultToolbar); } + @ReactProp(name = "availableFontNames") + public void setAvailableFontNames(@NonNull final PdfView view, @Nullable final ReadableArray availableFontNames) { + view.setAvailableFontNames(availableFontNames); + } + + @ReactProp(name = "selectedFontName") + public void setSelectedFontName(@NonNull final PdfView view, @Nullable final String selectedFontName) { + view.setSelectedFontName(selectedFontName); + } + @Nullable @Override public Map getExportedCustomDirectEventTypeConstants() { diff --git a/android/src/main/java/com/pspdfkit/views/PdfView.java b/android/src/main/java/com/pspdfkit/views/PdfView.java index 093c6e49..5bcdb240 100644 --- a/android/src/main/java/com/pspdfkit/views/PdfView.java +++ b/android/src/main/java/com/pspdfkit/views/PdfView.java @@ -4,6 +4,7 @@ import android.content.Context; import android.net.Uri; import android.util.AttributeSet; +import android.util.Log; import android.util.Pair; import android.view.Choreographer; import android.view.View; @@ -13,10 +14,14 @@ import androidx.annotation.Nullable; import androidx.fragment.app.FragmentManager; +import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.events.EventDispatcher; +import com.pspdfkit.PSPDFKit; import com.pspdfkit.annotations.Annotation; +import com.pspdfkit.annotations.AnnotationType; +import com.pspdfkit.annotations.configuration.FreeTextAnnotationConfiguration; import com.pspdfkit.configuration.activity.PdfActivityConfiguration; import com.pspdfkit.document.PdfDocument; import com.pspdfkit.document.PdfDocumentLoader; @@ -42,9 +47,11 @@ import com.pspdfkit.ui.PdfFragment; import com.pspdfkit.ui.PdfUiFragment; import com.pspdfkit.ui.PdfUiFragmentBuilder; +import com.pspdfkit.ui.fonts.Font; +import com.pspdfkit.ui.fonts.FontManager; import com.pspdfkit.ui.search.PdfSearchView; import com.pspdfkit.ui.search.PdfSearchViewInline; -import com.pspdfkit.ui.toolbar.MainToolbar; +import com.pspdfkit.ui.special_mode.controller.AnnotationTool; import com.pspdfkit.ui.toolbar.grouping.MenuItemGroupingRule; import org.json.JSONArray; @@ -84,6 +91,7 @@ public class PdfView extends FrameLayout { /** Key to use when setting the id argument of PdfFragments created by this PdfView. */ private static final String ARG_ROOT_ID = "root_id"; + private static final String TAG = "PdfView"; private FragmentManager fragmentManager; private EventDispatcher eventDispatcher; @@ -116,6 +124,18 @@ public class PdfView extends FrameLayout { /** We keep track if the inline search view is shown since we don't want to add a second navigation button while it is shown. */ private boolean isSearchViewShown = false; + /** Disposable keeping track of our subscription to update the annotation configuration on each emitted PdfFragment. */ + @Nullable + private Disposable updateAnnotationConfigurationDisposable; + + /** The currently configured array of available font names for free text annotations. */ + @Nullable + private ReadableArray availableFontNames; + + /** The currently configured default font name for free text annotations. */ + @Nullable + private String selectedFontName; + public PdfView(@NonNull Context context) { super(context); init(); @@ -233,6 +253,63 @@ public void setMenuItemGroupingRule(@NonNull MenuItemGroupingRule groupingRule) pdfViewModeController.setMenuItemGroupingRule(groupingRule); } + public void setAvailableFontNames(@Nullable final ReadableArray availableFontNames) { + this.availableFontNames = availableFontNames; + updateAnnotationConfiguration(); + } + + public void setSelectedFontName(@Nullable final String selectedFontName) { + this.selectedFontName = selectedFontName; + updateAnnotationConfiguration(); + } + + private void updateAnnotationConfiguration() { + if (updateAnnotationConfigurationDisposable != null) { + updateAnnotationConfigurationDisposable.dispose(); + } + + // First we create the new FreeTextAnnotationConfiguration. + FreeTextAnnotationConfiguration.Builder builder = FreeTextAnnotationConfiguration.builder(getContext()); + FontManager systemFontManager = PSPDFKit.getSystemFontManager(); + if (availableFontNames != null) { + // Custom list of available fonts is set. + final ArrayList availableFonts = new ArrayList<>(); + for (int i = 0; i < availableFontNames.size(); i++) { + final String fontName = availableFontNames.getString(i); + final Font font = systemFontManager.getFontByName(fontName); + if (font != null) { + availableFonts.add(font); + } else { + Log.w(TAG, String.format("Failed to add font %s to list of available fonts since it wasn't found in the list of system fonts.", fontName)); + } + } + builder.setAvailableFonts(availableFonts); + } + + if (selectedFontName != null) { + final Font defaultFont = systemFontManager.getFontByName(selectedFontName); + if (defaultFont != null) { + builder.setDefaultFont(defaultFont); + } else { + Log.w(TAG, String.format("Failed to set default font to %s since it wasn't found in the list of system fonts.", selectedFontName)); + } + } + + final FreeTextAnnotationConfiguration configuration = builder.build(); + // We want to set this on the current PdfFragment and all future ones. + // We use the observable emitting PdfFragments for this purpose. + updateAnnotationConfigurationDisposable = getPdfFragment() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(pdfFragment -> { + pdfFragment.getAnnotationConfiguration().put( + AnnotationTool.FREETEXT,configuration); + pdfFragment.getAnnotationConfiguration().put( + AnnotationType.FREETEXT,configuration); + pdfFragment.getAnnotationConfiguration().put( + AnnotationTool.FREETEXT_CALLOUT,configuration); + }); + } + public void setShowNavigationButtonInToolbar(final boolean showNavigationButtonInToolbar) { isNavigationButtonShown = showNavigationButtonInToolbar; pendingFragmentActions.add(getCurrentPdfUiFragment() diff --git a/index.js b/index.js index f1536056..637d4695 100644 --- a/index.js +++ b/index.js @@ -13,7 +13,7 @@ import { Platform, findNodeHandle, NativeModules, - UIManager + UIManager, } from "react-native"; class PSPDFKitView extends React.Component { @@ -23,7 +23,7 @@ class PSPDFKitView extends React.Component { render() { if (Platform.OS === "ios" || Platform.OS === "android") { const onCloseButtonPressedHandler = this.props.onCloseButtonPressed - ? event => { + ? (event) => { this.props.onCloseButtonPressed(event.nativeEvent); } : null; @@ -47,49 +47,49 @@ class PSPDFKitView extends React.Component { } } - _onStateChanged = event => { + _onStateChanged = (event) => { if (this.props.onStateChanged) { this.props.onStateChanged(event.nativeEvent); } }; - _onDocumentSaved = event => { + _onDocumentSaved = (event) => { if (this.props.onDocumentSaved) { this.props.onDocumentSaved(event.nativeEvent); } }; - _onDocumentSaveFailed = event => { + _onDocumentSaveFailed = (event) => { if (this.props.onDocumentSaveFailed) { this.props.onDocumentSaveFailed(event.nativeEvent); } }; - _onDocumentLoadFailed = event => { + _onDocumentLoadFailed = (event) => { if (this.props.onDocumentLoadFailed) { this.props.onDocumentLoadFailed(event.nativeEvent); } }; - _onAnnotationTapped = event => { + _onAnnotationTapped = (event) => { if (this.props.onAnnotationTapped) { this.props.onAnnotationTapped(event.nativeEvent); } }; - _onAnnotationsChanged = event => { + _onAnnotationsChanged = (event) => { if (this.props.onAnnotationsChanged) { this.props.onAnnotationsChanged(event.nativeEvent); } }; - _onNavigationButtonClicked = event => { + _onNavigationButtonClicked = (event) => { if (this.props.onNavigationButtonClicked) { this.props.onNavigationButtonClicked(event.nativeEvent); } }; - _onDataReturned = event => { + _onDataReturned = (event) => { let { requestId, result, error } = event.nativeEvent; let promise = this._requestMap[requestId]; if (result != undefined) { @@ -103,7 +103,7 @@ class PSPDFKitView extends React.Component { /** * Enters the annotation creation mode, showing the annotation creation toolbar. */ - enterAnnotationCreationMode = function() { + enterAnnotationCreationMode = function () { if (Platform.OS === "android") { UIManager.dispatchViewManagerCommand( findNodeHandle(this.refs.pdfView), @@ -121,7 +121,7 @@ class PSPDFKitView extends React.Component { /** * Exits the currently active mode, hiding all toolbars. */ - exitCurrentlyActiveMode = function() { + exitCurrentlyActiveMode = function () { if (Platform.OS === "android") { UIManager.dispatchViewManagerCommand( findNodeHandle(this.refs.pdfView), @@ -141,13 +141,13 @@ class PSPDFKitView extends React.Component { * * Returns a promise resolving to true if the document was saved, and false otherwise. */ - saveCurrentDocument = function() { + saveCurrentDocument = function () { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -175,13 +175,13 @@ class PSPDFKitView extends React.Component { * Returns a promise resolving an array with the following structure: * {'annotations' : [instantJson]} */ - getAnnotations = function(pageIndex, type) { + getAnnotations = function (pageIndex, type) { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -208,13 +208,13 @@ class PSPDFKitView extends React.Component { * * Returns a promise resolving to true if the annotation was added. Otherwise, returns false if an error has occurred. */ - addAnnotation = function(annotation) { + addAnnotation = function (annotation) { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -240,13 +240,13 @@ class PSPDFKitView extends React.Component { * * Returns a promise resolving to true if the annotation was removed. Otherwise, returns false if the annotation couldn't be found. */ - removeAnnotation = function(annotation) { + removeAnnotation = function (annotation) { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -270,13 +270,13 @@ class PSPDFKitView extends React.Component { * * Returns a promise resolving to document instant json (https://pspdfkit.com/guides/android/current/importing-exporting/instant-json/#instant-document-json-api-a56628). */ - getAllUnsavedAnnotations = function() { + getAllUnsavedAnnotations = function () { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -303,13 +303,13 @@ class PSPDFKitView extends React.Component { * Returns a promise resolving an array with the following structure: * {'annotations' : [instantJson]} */ - getAllAnnotations = function(type) { + getAllAnnotations = function (type) { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -336,13 +336,13 @@ class PSPDFKitView extends React.Component { * * Returns a promise resolving to true if the annotation was added. */ - addAnnotations = function(annotations) { + addAnnotations = function (annotations) { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -369,13 +369,13 @@ class PSPDFKitView extends React.Component { * Returns a promise resolving a dictionary with the following structure: * {'formElement' : value} or {'error' : 'Failed to get the form field value.'} */ - getFormFieldValue = function(fullyQualifiedName) { + getFormFieldValue = function (fullyQualifiedName) { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -403,13 +403,13 @@ class PSPDFKitView extends React.Component { * * Returns a promise resolving to true if the value was set, and false otherwise. */ - setFormFieldValue = function(fullyQualifiedName, value) { + setFormFieldValue = function (fullyQualifiedName, value) { if (Platform.OS === "android") { let requestId = this._nextRequestId++; let requestMap = this._requestMap; // We create a promise here that will be resolved once onDataReturned is called. - let promise = new Promise(function(resolve, reject) { + let promise = new Promise(function (resolve, reject) { requestMap[requestId] = { resolve: resolve, reject: reject }; }); @@ -439,7 +439,7 @@ class PSPDFKitView extends React.Component { * * @platform ios */ - setLeftBarButtonItems = function(items, viewMode, animated) { + setLeftBarButtonItems = function (items, viewMode, animated) { if (Platform.OS === "ios") { NativeModules.PSPDFKitViewManager.setLeftBarButtonItems( items, @@ -458,7 +458,7 @@ class PSPDFKitView extends React.Component { * ['outlineButtonItem', 'searchButtonItem'] or a dictionary with the following error {'error' : 'Failed to get the left bar button items.'} * @platform ios */ - getLeftBarButtonItemsForViewMode = function(viewMode) { + getLeftBarButtonItemsForViewMode = function (viewMode) { if (Platform.OS === "ios") { return NativeModules.PSPDFKitViewManager.getLeftBarButtonItemsForViewMode( viewMode, @@ -476,7 +476,7 @@ class PSPDFKitView extends React.Component { * * @platform ios */ - setRightBarButtonItems = function(items, viewMode, animated) { + setRightBarButtonItems = function (items, viewMode, animated) { if (Platform.OS === "ios") { NativeModules.PSPDFKitViewManager.setRightBarButtonItems( items, @@ -495,7 +495,7 @@ class PSPDFKitView extends React.Component { * ['annotationButtonItem', 'documentEditorButtonItem'] or a dictionary with the following error {'error' : 'Failed to get the right bar button items.'} * @platform ios */ - getRightBarButtonItemsForViewMode = function(viewMode) { + getRightBarButtonItemsForViewMode = function (viewMode) { if (Platform.OS === "ios") { return NativeModules.PSPDFKitViewManager.getRightBarButtonItemsForViewMode( viewMode, @@ -504,7 +504,7 @@ class PSPDFKitView extends React.Component { } }; - _getViewManagerConfig = viewManagerName => { + _getViewManagerConfig = (viewManagerName) => { const version = NativeModules.PlatformConstants.reactNativeVersion.minor; if (version >= 58) { return UIManager.getViewManagerConfig(viewManagerName); @@ -658,7 +658,31 @@ PSPDFKitView.propTypes = { * * @platform android */ - onNavigationButtonClicked: PropTypes.func + onNavigationButtonClicked: PropTypes.func, + /** + * availableFontNames: Can be used to specfiy the available font names in the font picker. + * + * Note on iOS: You need to set the desired font family names as `UIFontDescriptor`. See https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc + * See `CustomFontPicker` in https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/Catalog.ios.js + * + */ + availableFontNames: PropTypes.array, + /** + * selectedFontName: Can be used to specfiy the current selected font in the font picker. + * + * Note on iOS: You need to set the desired font family name as `UIFontDescriptor`. See https://developer.apple.com/documentation/uikit/uifontdescriptor?language=objc + * See `CustomFontPicker` in https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/Catalog.ios.js + * + * Note on Android: This is the default font that is selected, if the users changes the font that will become the new default. + */ + selectedFontName: PropTypes.string, + /** + * showDownloadableFonts: Can be used to show or hide the downloadable fonts section in the font picker. Defaults to showing a the downloadable fonts (true). + * See `CustomFontPicker` in https://github.com/PSPDFKit/react-native/blob/master/samples/Catalog/Catalog.ios.js + * + * @platform ios + */ + showDownloadableFonts: PropTypes.bool, }; if (Platform.OS === "ios" || Platform.OS === "android") { @@ -674,8 +698,8 @@ if (Platform.OS === "ios" || Platform.OS === "android") { accessibilityLiveRegion: true, importantForAccessibility: true, onLayout: true, - nativeID: true - } + nativeID: true, + }, } ); module.exports = PSPDFKitView; diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitView.h b/ios/RCTPSPDFKit/RCTPSPDFKitView.h index 546d96a8..530dd5ff 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitView.h +++ b/ios/RCTPSPDFKit/RCTPSPDFKitView.h @@ -30,6 +30,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) RCTBubblingEventBlock onAnnotationTapped; @property (nonatomic, copy) RCTBubblingEventBlock onAnnotationsChanged; @property (nonatomic, copy) RCTBubblingEventBlock onStateChanged; +@property (nonatomic, copy, nullable) NSArray *availableFontNames; +@property (nonatomic, copy, nullable) NSString *selectedFontName; +@property (nonatomic) BOOL showDownloadableFonts; /// Annotation Toolbar - (BOOL)enterAnnotationCreationMode; diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m index 40e2a66b..35007221 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m +++ b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m @@ -19,6 +19,20 @@ @import PSPDFKit; @import PSPDFKitUI; +// Static variables to allow communication between the React Native View Props and the custom font picker view controller. +static NSString *staticSelectedFontName; +static NSArray*staticAvailableFontNames; + +/** Defaults to YES. + + @see https://pspdfkit.com/api/ios/Classes/PSPDFFontPickerViewController.html#/c:objc(cs)PSPDFFontPickerViewController(py)showDownloadableFonts + */ +static BOOL staticShowDownloadableFonts = YES; + +// Custom font picker subclass to allow customizations. +@interface CustomFontPickerViewController : PSPDFFontPickerViewController +@end + @implementation RCTPSPDFKitViewManager RCT_EXPORT_MODULE() @@ -40,6 +54,7 @@ @implementation RCTPSPDFKitViewManager RCT_CUSTOM_VIEW_PROPERTY(configuration, PSPDFConfiguration, RCTPSPDFKitView) { if (json) { [view.pdfController updateConfigurationWithBuilder:^(PSPDFConfigurationBuilder *builder) { + [builder overrideClass:PSPDFFontPickerViewController.class withClass:CustomFontPickerViewController.class]; [builder setupFromJSON:json]; }]; } @@ -107,6 +122,27 @@ @implementation RCTPSPDFKitViewManager RCT_EXPORT_VIEW_PROPERTY(onStateChanged, RCTBubblingEventBlock) +RCT_CUSTOM_VIEW_PROPERTY(availableFontNames, NSArray, RCTPSPDFKitView) { + if (json && [RCTConvert NSArray:json]) { + view.availableFontNames = [RCTConvert NSArray:json]; + staticAvailableFontNames = view.availableFontNames; + } +} + +RCT_CUSTOM_VIEW_PROPERTY(selectedFontName, NSString, RCTPSPDFKitView) { + if (json && [RCTConvert NSString:json]) { + view.selectedFontName = [RCTConvert NSString:json]; + staticSelectedFontName = view.selectedFontName; + } +} + +RCT_CUSTOM_VIEW_PROPERTY(showDownloadableFonts, BOOL, RCTPSPDFKitView) { + if (json) { + view.showDownloadableFonts = [RCTConvert BOOL:json]; + staticShowDownloadableFonts = view.showDownloadableFonts; + } +} + 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]; @@ -288,3 +324,49 @@ - (UIView *)view { } @end + +@implementation CustomFontPickerViewController + +- (NSArray *)customFontFamilyDescriptors { + NSMutableArray *fontFamilyDescription = [NSMutableArray array]; + for (NSString *fontName in staticAvailableFontNames) { + [fontFamilyDescription addObject:[[UIFontDescriptor alloc] initWithFontAttributes:@{UIFontDescriptorNameAttribute: fontName}]]; + } + + return fontFamilyDescription; +} + +- (UIFont *)customSelectedFont { + // We bailout early if the passed selected font name is nil. + if (!staticSelectedFontName) { + return nil; + } + UIFontDescriptor *fontDescriptor = [[UIFontDescriptor alloc] initWithFontAttributes:@{UIFontDescriptorNameAttribute: staticSelectedFontName}]; + return [UIFont fontWithDescriptor:fontDescriptor size:12.0]; +} + +- (instancetype)initWithFontFamilyDescriptors:(NSArray *)fontFamilyDescriptors { + // Override the default font family descriptors if custom font descriptors are specified. + NSArray *customFontFamilyDescriptors = [self customFontFamilyDescriptors]; + if (customFontFamilyDescriptors.count) { + fontFamilyDescriptors = customFontFamilyDescriptors; + } + return [super initWithFontFamilyDescriptors:fontFamilyDescriptors]; +} + +- (void)dealloc { + // Reset the static variables. + staticSelectedFontName = nil; + staticAvailableFontNames = nil; + staticShowDownloadableFonts = YES; +} + +-(void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // Customize the font picker before it appears. + self.showDownloadableFonts = staticShowDownloadableFonts; + self.selectedFont = [self customSelectedFont]; +} + +@end diff --git a/samples/Catalog/Catalog.android.js b/samples/Catalog/Catalog.android.js index aa0cab9c..fddfe862 100644 --- a/samples/Catalog/Catalog.android.js +++ b/samples/Catalog/Catalog.android.js @@ -18,7 +18,7 @@ import { NativeModules, processColor, PermissionsAndroid, - Dimensions + Dimensions, } from "react-native"; import { createStackNavigator, createAppContainer } from "react-navigation"; @@ -36,7 +36,7 @@ const IMAGE_DOCUMENT = "file:///sdcard/android.png"; const CONFIGURATION_IMAGE_DOCUMENT = { showPageNumberOverlay: false, showPageLabels: false, - showThumbnailBar: "none" + showThumbnailBar: "none", }; const CONFIGURATION = { @@ -50,7 +50,7 @@ const CONFIGURATION = { // Settings this to false will disable all annotation editing enableAnnotationEditing: true, // Only stamps and square annotations will be editable, others can not be selected or otherwise modified. - editableAnnotationTypes: ["Stamp", "Square"] + editableAnnotationTypes: ["Stamp", "Square"], }; const examples = [ @@ -60,14 +60,14 @@ const examples = [ description: "Open document from your project assets folder", action: () => { PSPDFKit.present("file:///android_asset/Annual Report.pdf", {}) - .then(loaded => { + .then((loaded) => { console.log("Document was loaded successfully."); }) - .catch(error => { + .catch((error) => { console.log(error); }); PSPDFKit.setPageIndex(3, false); - } + }, }, { key: "item2", @@ -79,7 +79,7 @@ const examples = [ PSPDFKit.present(DOCUMENT, {}); }); }); - } + }, }, { key: "item3", @@ -91,7 +91,7 @@ const examples = [ PSPDFKit.presentImage(IMAGE_DOCUMENT, CONFIGURATION_IMAGE_DOCUMENT); }); }); - } + }, }, { key: "item4", @@ -102,49 +102,49 @@ const examples = [ requestExternalStoragePermission(function() { PSPDFKit.present(DOCUMENT, CONFIGURATION); }); - } + }, }, { key: "item5", name: "PDF View Component", description: "Show how to use the PSPDFKitView component with react-navigation.", - action: component => { + action: (component) => { component.props.navigation.navigate("PdfView"); - } + }, }, { key: "item6", name: "Event Listeners", description: "Show how to use the listeners exposed by PSPDFKitView component.", - action: component => { + action: (component) => { component.props.navigation.navigate("PdfViewListenersScreen"); - } + }, }, { key: "item7", name: "Programmatic Annotations", description: "Shows how to get and add new annotations using Instant JSON.", - action: component => { + action: (component) => { component.props.navigation.navigate("PdfViewInstantJsonScreen"); - } + }, }, { key: "item8", name: "Programmatic Form Filling", description: "Shows how to programatically read and write PDF form values.", - action: component => { + action: (component) => { component.props.navigation.navigate("PdfViewFormFillingScreen"); - } + }, }, { key: "item10", name: "Instant Example", description: "Shows how to open an instant document.", - action: component => { + action: (component) => { component.props.navigation.navigate("InstantExampleScreen"); - } + }, }, { key: "item11", @@ -155,35 +155,46 @@ const examples = [ console.log(PSPDFKit); console.log(PSPDFKit.versionString); // console.log(NativeModules) - } + }, }, { key: "item12", name: "Annotation Processing", description: "Shows how to embed, flatten, remove, and print annotations, then present the newly processed document.", - action: component => { + action: (component) => { extractFromAssetsIfMissing("Annual Report.pdf", function() { component.props.navigation.push("AnnotationProcessing"); }); - } + }, }, { key: "item13", name: "Hiding Toolbar", description: "Shows how to hide the main toolbar while keeping the thumbnail bar visible.", - action: component => { + action: (component) => { extractFromAssetsIfMissing("Annual Report.pdf", function() { component.props.navigation.push("HidingToolbar"); }); - } - } + }, + }, + { + key: "item14", + name: "Custom Font Picker", + description: + "Shows how to customize the font picker for free text annotations.", + action: (component) => { + extractFromAssetsIfMissing("Annual Report.pdf", function() { + component.props.navigation.push("CustomFontPicker"); + }); + }, + }, ]; function extractFromAssetsIfMissing(assetFile, callback) { RNFS.exists("/sdcard/" + assetFile) - .then(exist => { + .then((exist) => { if (exist) { console.log(assetFile + " exists in the external storage directory."); callback(); @@ -193,7 +204,7 @@ function extractFromAssetsIfMissing(assetFile, callback) { " does not exist, extracting it from assets folder to the external storage directory." ); RNFS.existsAssets(assetFile) - .then(exist => { + .then((exist) => { // Check if the file is present in the assets folder. if (exist) { // File exists so it can be extracted to the external storage directory. @@ -202,7 +213,7 @@ function extractFromAssetsIfMissing(assetFile, callback) { // File copied successfully from assets folder to external storage directory. callback(); }) - .catch(error => { + .catch((error) => { console.log(error); }); } else { @@ -213,12 +224,12 @@ function extractFromAssetsIfMissing(assetFile, callback) { ); } }) - .catch(error => { + .catch((error) => { console.log(error); }); } }) - .catch(error => { + .catch((error) => { console.log(error); }); } @@ -241,14 +252,14 @@ async function requestExternalStoragePermission(callback) { class CatalogScreen extends Component<{}> { static navigationOptions = { - title: "Catalog" + title: "Catalog", }; // Initialize the hardcoded data constructor(props) { super(props); this.state = { - dataSource: examples + dataSource: examples, }; } @@ -301,7 +312,7 @@ class PdfViewScreen extends Component<{}> { return { // Since the PSPDFKitView provides it's own toolbar and back button we don't need a header. - header: null + header: null, }; }; @@ -311,7 +322,7 @@ class PdfViewScreen extends Component<{}> { currentPageIndex: 0, pageCount: 0, annotationCreationActive: false, - annotationEditingActive: false + annotationEditingActive: false, }; } @@ -326,7 +337,7 @@ class PdfViewScreen extends Component<{}> { } else { this.refs.pdfView.enterAnnotationCreationMode(); } - } + }, }); } @@ -348,26 +359,26 @@ class PdfViewScreen extends Component<{}> { configuration={{ toolbarTitle: "My Awesome Report", backgroundColor: processColor("lightgrey"), - showThumbnailBar: "scrollable" + showThumbnailBar: "scrollable", }} pageIndex={this.state.currentPageIndex} fragmentTag="PDF1" showNavigationButtonInToolbar={true} - onNavigationButtonClicked={event => { + onNavigationButtonClicked={(event) => { this.props.navigation.goBack(); }} menuItemGrouping={[ "freetext", { key: "markup", items: ["highlight", "underline"] }, "ink", - "image" + "image", ]} - onStateChanged={event => { + onStateChanged={(event) => { this.setState({ currentPageIndex: event.currentPageIndex, pageCount: event.pageCount, annotationCreationActive: event.annotationCreationActive, - annotationEditingActive: event.annotationEditingActive + annotationEditingActive: event.annotationEditingActive, }); }} style={{ flex: 1, color: pspdfkitColor }} @@ -377,7 +388,7 @@ class PdfViewScreen extends Component<{}> { flexDirection: "row", height: 40, alignItems: "center", - padding: 10 + padding: 10, }} > @@ -389,9 +400,9 @@ class PdfViewScreen extends Component<{}> {