Skip to content
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

Add Signature props: signatureCreationModes and signatureColorOptions #418

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
76 changes: 76 additions & 0 deletions android/src/main/java/com/pspdfkit/react/ConfigurationAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package com.pspdfkit.react;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;

import androidx.annotation.NonNull;
Expand All @@ -31,8 +32,11 @@
import com.pspdfkit.configuration.page.PageScrollDirection;
import com.pspdfkit.configuration.page.PageScrollMode;
import com.pspdfkit.configuration.sharing.ShareFeatures;
import com.pspdfkit.configuration.signatures.SignatureColorOptions;
import com.pspdfkit.configuration.signatures.SignatureCreationMode;
import com.pspdfkit.configuration.signatures.SignatureSavingStrategy;
import com.pspdfkit.preferences.PSPDFKitPreferences;
import com.pspdfkit.react.helper.ColorHelper;

import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -114,6 +118,10 @@ public class ConfigurationAdapter {
private static final String ENABLE_MAGNIFIER = "enableMagnifier";
private static final String ENABLED_MEASUREMENT_TOOL_SNAPPING = "enableMeasurementToolSnapping";

// Signature presentation options
private static final String SIGNATURE_CREATION_MODES = "signatureCreationModes";
private static final String SIGNATURE_COLOR_OPTIONS = "signatureColorOptions";

// Deprecated Options
/**
* @deprecated This key word was deprecated with PSPDFKit for React Native 2.1.
Expand Down Expand Up @@ -322,6 +330,14 @@ public ConfigurationAdapter(@NonNull final Context context, ReadableMap configur
if (key != null) {
configureMeasurementToolSnappingEnabled(context, configuration.getBoolean(key));
}
key = getKeyOrNull(configuration, SIGNATURE_CREATION_MODES);
if (key != null) {
configureSignatureCreationModes(configuration.getArray(key));
}
key = getKeyOrNull(configuration, SIGNATURE_COLOR_OPTIONS);
if (key != null) {
configureSignatureColorOptions(context, configuration.getArray(key));
}
}
}

Expand Down Expand Up @@ -704,6 +720,66 @@ private void configureMeasurementToolSnappingEnabled(Context context, final Bool
PSPDFKitPreferences.get(context).setMeasurementSnappingEnabled(snappingEnabled);
}

private void configureSignatureCreationModes(@Nullable final ReadableArray signatureCreationModes) {
if (signatureCreationModes == null) {
// If explicit null is passed we disable all signature modes.
configuration.signatureCreationModes(new ArrayList<>());
return;
}
List<Object> sigCreationModesList = signatureCreationModes.toArrayList();

// Finally create the actual list of enabled signature creation modes.
List<SignatureCreationMode> parsedTypes = new ArrayList<>();
for (Object item : sigCreationModesList) {
String signatureCreationMode = item.toString();
try {
parsedTypes.add(SignatureCreationMode.valueOf(signatureCreationMode.toUpperCase(Locale.ENGLISH)));
} catch (IllegalArgumentException ex) {
Log.e(LOG_TAG,
String.format("Illegal option %s provided for configuration option %s. Skipping this %s.", signatureCreationMode, SIGNATURE_CREATION_MODES, signatureCreationMode),
ex);
}
}
configuration.signatureCreationModes(parsedTypes);
}

private void configureSignatureColorOptions(final Context context, @Nullable final ReadableArray signatureCreationColors) {
if (signatureCreationColors == null) {
return;
}

List<Object> sigCreationColors = signatureCreationColors.toArrayList();

SignatureColorOptions defaultColors = SignatureColorOptions.fromDefaults();
int[] configuredColors = new int[] { defaultColors.option1(context),
defaultColors.option2(context), defaultColors.option3(context) };

int i = 0;
for (Object rgbaColorOrName : sigCreationColors) {
// only 3 colors are supported
if (i == 3) break;

String color = rgbaColorOrName.toString();

// attempt to resolve colors, if no match
// we'll use the default value at this index
if (color.contains("rgb(")) {
configuredColors[i] = ColorHelper.rgb(color);
}
else {
// hex or named colors
configuredColors[i] = Color.parseColor(color);
}

i++;
}

configuration.signatureColorOptions(SignatureColorOptions.fromColorInt(
configuredColors[0],
configuredColors[1],
configuredColors[2]));
}

public PdfActivityConfiguration build() {
return configuration.build();
}
Expand Down
61 changes: 61 additions & 0 deletions ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@
#define BookmarkSortOrderMap @{@"custom" : @(PSPDFBookmarkManagerSortOrderCustom), \
@"pageBased" : @(PSPDFBookmarkManagerSortOrderPageBased)} \

#define SignatureCreationModeMap @{@"draw": @(PSPDFSignatureCreationModeDraw), \
@"image": @(PSPDFSignatureCreationModeImage), \
@"type": @(PSPDFSignatureCreationModeType)} \

@implementation RCTConvert (PSPDFConfiguration)

+ (PSPDFConfiguration *)PSPDFConfiguration:(id)json {
Expand Down Expand Up @@ -563,6 +567,19 @@ + (NSDictionary *)convertConfiguration:(PSPDFViewController *)viewController {
[convertedConfiguration setObject:[RCTConvert findKeyForValue:configuration.bookmarkSortOrder
inDictionary:BookmarkSortOrderMap] forKey:@"iOSBookmarkSortOrder"];

[convertedConfiguration setObject:[RCTConvert findKeysForValues:[NSSet setWithArray:configuration.signatureCreationConfiguration.availableModes]
inDictionary:SignatureCreationModeMap]
forKey:@"signatureCreationModes"];

NSMutableArray *signatureCreationColors = [NSMutableArray array];
[configuration.signatureCreationConfiguration.colors enumerateObjectsUsingBlock:^(UIColor * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

NSString *hexColor = [NSString stringWithFormat:@"#%02lX", [obj hex]];

[signatureCreationColors addObject:hexColor];
}];
[convertedConfiguration setObject:signatureCreationColors forKey:@"signatureCreationColors"];

return convertedConfiguration;
}

Expand Down Expand Up @@ -694,6 +711,8 @@ - (void)setupFromJSON:(id)json {
self.editableAnnotationTypes = [editableTypes copy];
}

[self setRCTSignatureCreationConfiguration:dictionary];

// Deprecated Options

// Use `scrollDirection` instead.
Expand Down Expand Up @@ -739,4 +758,46 @@ - (void)setRCTSharingConfigurations:(NSArray<NSDictionary *> *)sharingConfigurat
self.sharingConfigurations = rnSharingConfigurations;
}

- (void)setRCTSignatureCreationConfiguration:(NSDictionary *)configuration {
PSPDFSignatureCreationConfigurationBuilder *builder = [PSPDFSignatureCreationConfigurationBuilder alloc];

// important: set all default values
[builder reset];

if (configuration[@"signatureCreationModes"]) {
NSSet *selectedModes = [NSSet setWithArray:[RCTConvert NSArray:configuration[@"signatureCreationModes"]]];

NSMutableArray *mappedValues = [NSMutableArray array];
for (NSString *signatureCreationModeString in selectedModes) {
NSNumber *value = [SignatureCreationModeMap valueForKey:signatureCreationModeString];
if (value != nil) {
[mappedValues addObject:value];
}
}

builder.availableModes = mappedValues;
}

if (configuration[@"signatureColorOptions"]) {
NSArray *signatureColors = [RCTConvert NSArray:configuration[@"signatureColorOptions"]];

NSMutableArray *resolvedColors = [NSMutableArray array];
for (NSString *colorString in signatureColors) {
if ([colorString hasPrefix:@"rgb("]) {
[resolvedColors addObject: [UIColor rgb:colorString]];
}
else if ([colorString hasPrefix:@"#"]){
[resolvedColors addObject: [[UIColor new] initWithHexString:colorString]];
}
else {
[resolvedColors addObject: [UIColor colorFromName:colorString]];
}
}

builder.colors = resolvedColors;
}

self.signatureCreationConfiguration = [builder build];
}

@end
14 changes: 11 additions & 3 deletions ios/RCTPSPDFKit/UIColor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import UIKit

extension UIColor {
public convenience init?(hexString: String) {
@objc public convenience init?(hexString: String) {
let r, g, b, a: CGFloat

if hexString.hasPrefix("#") {
Expand Down Expand Up @@ -51,7 +51,7 @@ extension UIColor {
}


public static func colorFromName(_ name: String) -> UIColor? {
@objc public static func colorFromName(_ name: String) -> UIColor? {
let selector = Selector("\(name)Color")
if UIColor.self.responds(to: selector) {
let color = UIColor.self.perform(selector).takeUnretainedValue()
Expand All @@ -61,7 +61,7 @@ extension UIColor {
return nil
}

public static func rgb(_ colorValue: String) -> UIColor? {
@objc public static func rgb(_ colorValue: String) -> UIColor? {
let colorsComponentString: String = colorValue.replacingOccurrences(of: "rgb(", with: "").replacingOccurrences(of: ")", with: "").replacingOccurrences(of: " ", with: "")
let colorComponents = colorsComponentString.components(separatedBy: ",")

Expand Down Expand Up @@ -104,4 +104,12 @@ extension UIColor {
+ Int(green * 255) << 8
+ Int(blue * 255)
}

@objc public var hex: Int {
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return Int(red * 255) << 16
+ Int(green * 255) << 8
+ Int(blue * 255)
}
}
49 changes: 47 additions & 2 deletions src/configuration/PDFConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ import { MeasurementValueConfiguration } from './../measurements/Measurements';
* @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.
* @property { PDFConfiguration.RemoteDocumentConfiguration } [remoteDocumentConfiguration] The configuration when downloading a document from a remote URL.
*/
* @property { PDFConfiguration.SignatureCreationModes[] } [signatureCreationModes] The signature creation modes that should be available in the signature picker.
* @property { PDFConfiguration.SignatureColorOptions[] } [signatureColorOptions] The color options that should be available in the signature picker, max of 3 colors are supported. If all 3 colors are not provided, defaults will be used in their place.
*/

export class PDFConfiguration {

Expand Down Expand Up @@ -475,6 +477,16 @@ export class PDFConfiguration {
* The configuration when downloading a document from a remote URL.
*/
remoteDocumentConfiguration?: RemoteDocumentConfiguration;

/**
* The signature creation modes that should be available in the signature picker.
*/
signatureCreationModes?: PDFConfiguration.SignatureCreationModes[];

/**
* The signature color options that should be available in the signature picker, max of 3 colors are supported. If all 3 colors are not provided, defaults will be used in their place.
*/
signatureColorOptions?: PDFConfiguration.SignatureColorOptions[];
}

export namespace PDFConfiguration {
Expand Down Expand Up @@ -1000,6 +1012,37 @@ export namespace PDFConfiguration {
*/
PAGE_BASED: 'pageBased'
} as const;

/**
* The possible ways in which the user can input their signature.
* @readonly
* @enum {string} SignatureCreationModes
*/
export const SignatureCreationModes = {
/**
* The user draws their signature. For example using a finger or stylus.
*/
DRAW: 'draw',
/**
* The user selects an existing image of their signature from their photo library or files, or takes
* a photo of their signature written on a piece of paper.
*/
IMAGE: 'image',
/**
* The user types their name and selects a style for their signature from a small number of fonts.
*/
TYPE: 'type'
} as const;

/**
* Color defined by a hex string of RGB values.
*/
export type HexColor = `#${string}`;

/**
* Color defined by RGB values.
*/
export type RGBColor = `rgb(${number},${number},${number})`;

export type BooleanType = ValueOf<typeof BooleanType>;
export type ScrollDirection = ValueOf<typeof ScrollDirection>;
Expand All @@ -1023,6 +1066,8 @@ export namespace PDFConfiguration {
export type IOSLinkAction = ValueOf<typeof IOSLinkAction>;
export type IOSDrawCreateMode = ValueOf<typeof IOSDrawCreateMode>;
export type IOSBookmarkSortOrder = ValueOf<typeof IOSBookmarkSortOrder>;
export type SignatureCreationModes = ValueOf<typeof SignatureCreationModes>;
export type SignatureColorOptions = HexColor | RGBColor | string;
}

/**
Expand All @@ -1047,4 +1092,4 @@ T extends `${infer F1}${infer F2}${infer R}` ? (
T extends `${infer F}${infer R}` ? `${Uppercase<F> | Lowercase<F>}${AnyCase<R>}` :
"";

type ValueOf<T> = T[keyof T];
type ValueOf<T> = T[keyof T];