From 92ff22723434a5227649044b9bcca49c7fc0eb33 Mon Sep 17 00:00:00 2001 From: kmathew-pdftron <97121165+kmathew-pdftron@users.noreply.github.com> Date: Tue, 5 Jul 2022 15:48:31 -0700 Subject: [PATCH] Hygen code generator (#508) * prop-generator * hygen changes * prop-generator regex injection and script * adding injection comments * Hygen method-generator * adding comment * changes to prop-generator template * comments for method injection * final change * Updating JS files * Spelling mistake * extracting into a method * more improvemets * mistake from testing * Updating JS files * Updating package version * refactoring method generator * Updating package.json * Updating package version * improved prop generator * fixed errors for method generator * fixes and improvements for android side of method generator * renamed and fixed bugs with helpers, made fixes and improvements for ios side of method generator * finished prop and method generators * new directory for listener generator * Updating package version * listener generator injection for DocumentView.tsx * Updating JS files * fixed method generator to handle 0 params + fix for listener generator * Updating package version * listener generator android side * listener generator ios side * fixed bug * fixed indent and newline issues * changed wording of some prompts * added more comments * Updating JS files * re-check * Updating package version Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Terry Yoon --- .hygen.js | 169 ++++++++++++++++++ _templates/generator/help/index.ejs.t | 5 + _templates/generator/new/hello.ejs.t | 18 ++ _templates/generator/with-prompt/hello.ejs.t | 18 ++ _templates/generator/with-prompt/prompt.js | 14 ++ .../new/ConstantsjavaEvent.ejs.t | 6 + .../new/ConstantsjavaKey.ejs.t | 15 ++ .../new/DocumentViewjava.ejs.t | 31 ++++ .../new/DocumentViewtsxOnChange.ejs.t | 20 +++ .../new/DocumentViewtsxProp.ejs.t | 11 ++ .../new/RNTPTDocumentViewManagerm.ejs.t | 28 +++ .../new/RNTPTDocumentViewh.ejs.t | 6 + _templates/listener-generator/new/index.js | 21 +++ .../new/DocumentViewModule.ejs.t | 24 +++ .../new/DocumentViewViewManagerjava.ejs.t | 15 ++ .../new/DocumentViewjava.ejs.t | 9 + .../new/DocumentViewtsx.ejs.t | 21 +++ .../new/RNTPTDocumentViewManagerh.ejs.t | 7 + .../new/RNTPTDocumentViewManagerm.ejs.t | 15 ++ .../new/RNTPTDocumentViewModulem.ejs.t | 27 +++ .../new/RNTPTDocumentViewh.ejs.t | 13 ++ .../new/RNTPTDocumentViewm.ejs.t | 17 ++ _templates/method-generator/new/index.js | 26 +++ .../prop-generator/new/DocumentViewJava.ejs.t | 8 + .../new/DocumentViewViewManagerJava.ejs.t | 9 + .../prop-generator/new/DocumentViewtsx.ejs.t | 16 ++ .../new/RNTPTDocumentViewManager.ejs.t | 21 +++ .../new/RNTPTDocumentViewh.ejs.t | 18 ++ .../new/RNTPTDocumentViewm.ejs.t | 20 +++ _templates/prop-generator/new/index.js | 43 +++++ .../modules/DocumentViewModule.java | 2 + .../pdftron/reactnative/utils/Constants.java | 4 + .../viewmanagers/DocumentViewViewManager.java | 6 +- .../reactnative/views/DocumentView.java | 6 + ios/RNTPTDocumentView.h | 5 + ios/RNTPTDocumentView.m | 2 + ios/RNTPTDocumentViewManager.h | 2 + ios/RNTPTDocumentViewManager.m | 6 + ios/RNTPTDocumentViewModule.m | 2 + lib/src/DocumentView/DocumentView.js | 3 + package.json | 2 +- src/DocumentView/DocumentView.tsx | 6 + 42 files changed, 715 insertions(+), 2 deletions(-) create mode 100644 .hygen.js create mode 100644 _templates/generator/help/index.ejs.t create mode 100644 _templates/generator/new/hello.ejs.t create mode 100644 _templates/generator/with-prompt/hello.ejs.t create mode 100644 _templates/generator/with-prompt/prompt.js create mode 100644 _templates/listener-generator/new/ConstantsjavaEvent.ejs.t create mode 100644 _templates/listener-generator/new/ConstantsjavaKey.ejs.t create mode 100644 _templates/listener-generator/new/DocumentViewjava.ejs.t create mode 100644 _templates/listener-generator/new/DocumentViewtsxOnChange.ejs.t create mode 100644 _templates/listener-generator/new/DocumentViewtsxProp.ejs.t create mode 100644 _templates/listener-generator/new/RNTPTDocumentViewManagerm.ejs.t create mode 100644 _templates/listener-generator/new/RNTPTDocumentViewh.ejs.t create mode 100644 _templates/listener-generator/new/index.js create mode 100644 _templates/method-generator/new/DocumentViewModule.ejs.t create mode 100644 _templates/method-generator/new/DocumentViewViewManagerjava.ejs.t create mode 100644 _templates/method-generator/new/DocumentViewjava.ejs.t create mode 100644 _templates/method-generator/new/DocumentViewtsx.ejs.t create mode 100644 _templates/method-generator/new/RNTPTDocumentViewManagerh.ejs.t create mode 100644 _templates/method-generator/new/RNTPTDocumentViewManagerm.ejs.t create mode 100644 _templates/method-generator/new/RNTPTDocumentViewModulem.ejs.t create mode 100644 _templates/method-generator/new/RNTPTDocumentViewh.ejs.t create mode 100644 _templates/method-generator/new/RNTPTDocumentViewm.ejs.t create mode 100644 _templates/method-generator/new/index.js create mode 100644 _templates/prop-generator/new/DocumentViewJava.ejs.t create mode 100644 _templates/prop-generator/new/DocumentViewViewManagerJava.ejs.t create mode 100644 _templates/prop-generator/new/DocumentViewtsx.ejs.t create mode 100644 _templates/prop-generator/new/RNTPTDocumentViewManager.ejs.t create mode 100644 _templates/prop-generator/new/RNTPTDocumentViewh.ejs.t create mode 100644 _templates/prop-generator/new/RNTPTDocumentViewm.ejs.t create mode 100644 _templates/prop-generator/new/index.js diff --git a/.hygen.js b/.hygen.js new file mode 100644 index 000000000..2e5ff7eb0 --- /dev/null +++ b/.hygen.js @@ -0,0 +1,169 @@ +module.exports = { + helpers: { + /** + * Converts the parameter list of a React Native function into a parameter list of an Android function. + * e.g. 'flag: boolean, page: int' => 'boolean flag, int page' or 'final boolean flag, final int page' + * @param params React Native parameter list string + * @param setFinal Whether to add the 'final' keyword in front of each parameter + * @returns {string} Android parameter list string + */ + androidParams: (params, setFinal) => { + let arguments = '' + let finalWord = setFinal ? 'final ' : '' + + // assuming no nested maps, remove the params inside maps (in between {} or Record<>) + // so that the top level parameters can be properly split by commas + params = params.replace(/((?<=\{)(.*?)(?=}))|((?<=Record<)(.*?)(?=>))/g, '') + + params.split(',').forEach(param => { + let name = param.substring(0, param.indexOf(':')).trim() + let type = param.substring(param.indexOf(':') + 1).trim() + + if ((type.startsWith('{') && type.endsWith('}')) || + (type.startsWith('Record<') && type.endsWith('>')) || + type.startsWith('AnnotOptions.')) { + type = 'ReadableMap' + } else if (type.startsWith('Config.') || type === 'string') { + type = 'String' + } else if (type.startsWith('Array<') && type.endsWith('>')) { + type = 'ReadableArray' + } + + arguments += finalWord + type + ' ' + name + ', ' + }) + + arguments = arguments.substring(0, arguments.length - 2) + return arguments + }, + /** + * Converts the parameter list of a React Native function into a parameter list of an iOS function. + * e.g. 'flag: boolean, page: int' => 'flag:(BOOL)flag page:(NSInteger)page' + * @param params React Native parameter list string + * @param format Whether to separate each parameter by newlines + * @returns {string} iOS parameter list string + */ + iOSParams: (params, format) => { + let arguments = '' + let formatStr = format ? '\n ' : ' ' + + params = params.replace(/((?<=\{)(.*?)(?=}))|((?<=Record<)(.*?)(?=>))/g, '') + + params.split(',').forEach(param => { + let name = param.substring(0, param.indexOf(':')).trim() + let type = param.substring(param.indexOf(':') + 1).trim() + + if ((type.startsWith('{') && type.endsWith('}')) || + (type.startsWith('Record<') && type.endsWith('>')) || + type.startsWith('AnnotOptions.')) { + type = 'NSDictionary *' + } else if (type === 'boolean') { + type = 'BOOL' + } else if (type === 'int') { + type = 'NSInteger' + } else if (type.startsWith('Config.') || type === 'string') { + type = 'NSString *' + } else if (type.startsWith('Array<') && type.endsWith('>')) { + type = 'NSArray *' + } + + arguments += name + ':(' + type + ')' + name + formatStr + }) + + arguments = arguments.substring(0, arguments.length - formatStr.length) + return arguments + }, + /** + * Converts the parameter list of a React Native function into arguments when calling an Android function. + * e.g. 'flag: boolean, page: int' => 'flag, page' + * @param params React Native parameter list string + * @returns {string} Android arguments string + */ + androidArgs: params => { + let arguments = '' + + params = params.replace(/((?<=\{)(.*?)(?=}))|((?<=Record<)(.*?)(?=>))/g, '') + + params.split(',').forEach(param => { + arguments += param.substring(0, param.indexOf(':')).trim() + ', ' + }) + + arguments = arguments.substring(0, arguments.length - 2) + return arguments + }, + /** + * Converts the parameter list of a React Native function into arguments when calling an iOS function. + * e.g. 'flag: boolean, page: int' => 'flag:flag page:page' + * @param params React Native parameter list string + * @returns {string} iOS arguments string + */ + iOSArgs: params => { + let arguments = '' + + params = params.replace(/((?<=\{)(.*?)(?=}))|((?<=Record<)(.*?)(?=>))/g, '') + + params.split(',').forEach(param => { + let name = param.substring(0, param.indexOf(':')).trim() + arguments += name + ':' + name + ' ' + }) + + arguments = arguments.substring(0, arguments.length - 1) + return arguments + }, + /** + * Converts the React Native prop type into a corresponding Android type. + * @param type React Native prop type + * @returns {string|*} Android prop type; returns given param if no match is found + */ + androidPropType: type => { + if (type === 'bool') { + return 'boolean' + } else if (type === 'string' || type === 'oneOf') { + return 'String' + } else if (type === 'arrayOf') { + return '@NonNull ReadableArray' + } else { + return type + } + }, + /** + * Converts the React Native function return type into a corresponding Android type. + * @param type React Native function return type + * @returns {string|*} Android return type; returns given param if no match is found + */ + androidReturnType: type => { + if (type.startsWith('Config.') || type === 'string') { + return 'String' + } else if ((type.startsWith('{') && type.endsWith('}')) || + (type.startsWith('Record<') && type.endsWith('>')) || + type.startsWith('AnnotOptions.')) { + return 'WritableMap' + } else if (type.startsWith('Array<') && type.endsWith('>')) { + return 'WritableArray' + } else { + return type + } + }, + /** + * Converts the React Native function return type into a corresponding iOS type. + * @param type React Native function return type + * @returns {string|*} iOS return type; returns given param if no match is found + */ + iOSReturnType: type => { + if (type === 'boolean') { + return 'BOOL' + } else if (type === 'int') { + return 'NSInteger' + } else if (type.startsWith('Config.') || type === 'string') { + return 'NSString *' + } else if ((type.startsWith('{') && type.endsWith('}')) || + (type.startsWith('Record<') && type.endsWith('>')) || + type.startsWith('AnnotOptions.')) { + return 'NSDictionary *' + } else if (type.startsWith('Array<') && type.endsWith('>')) { + return 'NSArray *' + } else { + return type + } + } + } +} diff --git a/_templates/generator/help/index.ejs.t b/_templates/generator/help/index.ejs.t new file mode 100644 index 000000000..90a29aff2 --- /dev/null +++ b/_templates/generator/help/index.ejs.t @@ -0,0 +1,5 @@ +--- +message: | + hygen {bold generator new} --name [NAME] --action [ACTION] + hygen {bold generator with-prompt} --name [NAME] --action [ACTION] +--- \ No newline at end of file diff --git a/_templates/generator/new/hello.ejs.t b/_templates/generator/new/hello.ejs.t new file mode 100644 index 000000000..5680d9639 --- /dev/null +++ b/_templates/generator/new/hello.ejs.t @@ -0,0 +1,18 @@ +--- +to: _templates/<%= name %>/<%= action || 'new' %>/hello.ejs.t +--- +--- +to: app/hello.js +--- +const hello = ``` +Hello! +This is your first hygen template. + +Learn what it can do here: + +https://github.com/jondot/hygen +``` + +console.log(hello) + + diff --git a/_templates/generator/with-prompt/hello.ejs.t b/_templates/generator/with-prompt/hello.ejs.t new file mode 100644 index 000000000..ba6abc562 --- /dev/null +++ b/_templates/generator/with-prompt/hello.ejs.t @@ -0,0 +1,18 @@ +--- +to: _templates/<%= name %>/<%= action || 'new' %>/hello.ejs.t +--- +--- +to: app/hello.js +--- +const hello = ``` +Hello! +This is your first prompt based hygen template. + +Learn what it can do here: + +https://github.com/jondot/hygen +``` + +console.log(hello) + + diff --git a/_templates/generator/with-prompt/prompt.js b/_templates/generator/with-prompt/prompt.js new file mode 100644 index 000000000..76ea532a6 --- /dev/null +++ b/_templates/generator/with-prompt/prompt.js @@ -0,0 +1,14 @@ +--- +to: _templates/<%= name %>/<%= action || 'new' %>/prompt.js +--- + +// see types of prompts: +// https://github.com/enquirer/enquirer/tree/master/examples +// +module.exports = [ + { + type: 'input', + name: 'message', + message: "What's your message?" + } +] diff --git a/_templates/listener-generator/new/ConstantsjavaEvent.ejs.t b/_templates/listener-generator/new/ConstantsjavaEvent.ejs.t new file mode 100644 index 000000000..d6887bd31 --- /dev/null +++ b/_templates/listener-generator/new/ConstantsjavaEvent.ejs.t @@ -0,0 +1,6 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/utils/Constants.java +after: // Hygen Generated Event Listeners +--- + public static final String <%= h.changeCase.constantCase(name) %> = "<%= name %>";<% -%> diff --git a/_templates/listener-generator/new/ConstantsjavaKey.ejs.t b/_templates/listener-generator/new/ConstantsjavaKey.ejs.t new file mode 100644 index 000000000..17e9dff61 --- /dev/null +++ b/_templates/listener-generator/new/ConstantsjavaKey.ejs.t @@ -0,0 +1,15 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/utils/Constants.java +after: // Hygen Generated Keys +--- +<% keys = '' + if (params !== '') { + params.split(',').forEach(param => { + argName = param.split(':')[0].trim() + keys += ' public static final String KEY_' + h.changeCase.constantCase(argName) + ' = "' + argName + '";\n' + }) + keys = keys.substring(0, keys.length - 1) + } +-%> +<%- keys %><% -%> diff --git a/_templates/listener-generator/new/DocumentViewjava.ejs.t b/_templates/listener-generator/new/DocumentViewjava.ejs.t new file mode 100644 index 000000000..48b9f4636 --- /dev/null +++ b/_templates/listener-generator/new/DocumentViewjava.ejs.t @@ -0,0 +1,31 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/views/DocumentView.java +after: // Hygen Generated Event Listeners +--- +<%# injecting lines to put the parameters into the WritableMap, e.g. params.putInt(KEY_PAGE_NUMBER, ); -%> +<% putArgs = '' + if (params !== '') { + params.split(',').forEach(param => { + argName = param.substring(0, param.indexOf(':')).trim() + argType = param.substring(param.indexOf(':') + 1).trim() + + if (argType.startsWith('AnnotOptions.')) { + argType = 'Map' + } else if (argType.startsWith('Config.') || argType === 'string') { + argType = 'String' + } else if (argType.startsWith('Array<') && argType.endsWith('>')) { + argType = 'Array' + } else { + argType = h.changeCase.upperCaseFirst(argType) + } + + putArgs += '\n // params.put' + argType + '(KEY_' + h.changeCase.constantCase(argName) + ', );' + }) + } +-%> + // uncomment and use to implement <%= name %> + // WritableMap params = Arguments.createMap(); + // params.putString(<%= h.changeCase.constantCase(name) %>, <%= h.changeCase.constantCase(name) %>);<%- putArgs %> + + // onReceiveNativeEvent(params); diff --git a/_templates/listener-generator/new/DocumentViewtsxOnChange.ejs.t b/_templates/listener-generator/new/DocumentViewtsxOnChange.ejs.t new file mode 100644 index 000000000..f7fdffe45 --- /dev/null +++ b/_templates/listener-generator/new/DocumentViewtsxOnChange.ejs.t @@ -0,0 +1,20 @@ +--- +inject: true +to: src/DocumentView/DocumentView.tsx +after: // Hygen Generated Event Listeners +--- +<%# injecting lines for each parameter, e.g. 'pageNumber': event.nativeEvent.pageNumber, -%> +<% args = '' + if (params !== '') { + args += '{' + params.split(',').forEach(param => { + argName = param.split(':')[0].trim() + args += '\n \'' + argName + '\': event.nativeEvent.' + argName + ',' + }) + args += '\n }' + } +-%> + } else if (event.nativeEvent.<%= name %>) { + if (this.props.<%= name %>) { + this.props.<%= name %>(<%- args %>); + }<% -%> diff --git a/_templates/listener-generator/new/DocumentViewtsxProp.ejs.t b/_templates/listener-generator/new/DocumentViewtsxProp.ejs.t new file mode 100644 index 000000000..8a18967a5 --- /dev/null +++ b/_templates/listener-generator/new/DocumentViewtsxProp.ejs.t @@ -0,0 +1,11 @@ +--- +inject: true +to: src/DocumentView/DocumentView.tsx +after: // Hygen Generated Props +--- +<% args = params.trim() + if (args !== '') { + args = 'event: { ' + args.replace(/\bint\b|\bdouble\b/g, 'number') + ' }' + } +-%> + <%= name %>: func<(<%- args %>) => void>(),<% -%> diff --git a/_templates/listener-generator/new/RNTPTDocumentViewManagerm.ejs.t b/_templates/listener-generator/new/RNTPTDocumentViewManagerm.ejs.t new file mode 100644 index 000000000..a19f46aa9 --- /dev/null +++ b/_templates/listener-generator/new/RNTPTDocumentViewManagerm.ejs.t @@ -0,0 +1,28 @@ +--- +inject: true +to: ios/RNTPTDocumentViewManager.m +after: // Hygen Generated Event Listeners +--- +<%# injecting lines for each parameter, e.g. @"pageNumber": @(pageNumber), -%> +<% args = '' + if (params !== '') { + params.split(',').forEach(param => { + argName = param.substring(0, param.indexOf(':')).trim() + argType = param.substring(param.indexOf(':') + 1).trim() + + if (argType === 'int' || argType === 'double' || argType === 'boolean' ) { + args += '\n @"' + argName + '": @(' + argName + '),' + } else { + args += '\n @"' + argName + '": ' + argName + ',' + } + }) + } +-%> +- (void)<%= name %>:(RNTPTDocumentView *)sender<%- params === '' ? '' : ' ' + h.iOSParams(params, false) %> +{ + if (sender.onChange) { + sender.onChange(@{ + @"<%= name %>": @"<%= name %>",<%- args %> + }); + } +} diff --git a/_templates/listener-generator/new/RNTPTDocumentViewh.ejs.t b/_templates/listener-generator/new/RNTPTDocumentViewh.ejs.t new file mode 100644 index 000000000..0aadebaf9 --- /dev/null +++ b/_templates/listener-generator/new/RNTPTDocumentViewh.ejs.t @@ -0,0 +1,6 @@ +--- +inject: true +to: ios/RNTPTDocumentView.h +after: // Hygen Generated Event Listeners +--- +- (void)<%= name %>:(RNTPTDocumentView *)sender<%- params === '' ? '' : ' ' + h.iOSParams(params, false) %>; diff --git a/_templates/listener-generator/new/index.js b/_templates/listener-generator/new/index.js new file mode 100644 index 000000000..da41619b6 --- /dev/null +++ b/_templates/listener-generator/new/index.js @@ -0,0 +1,21 @@ +module.exports = { + prompt: ({ inquirer }) => { + // defining questions in arrays ensures all questions are asked before next prompt is executed + const questions = [ + { + type: 'input', + name: 'name', + message: 'Name of event listener? (ex: onLayoutChanged)', + }, + { + type: 'input', + name: 'params', + message: 'Parameter list of React Native listener (comma separated)? Use either int or double for number\n (ex: previousPageNumber: int, pageNumber: int, ...)\n', + } + ] + + // returning the answers to the prompt + return inquirer + .prompt(questions) + }, +} diff --git a/_templates/method-generator/new/DocumentViewModule.ejs.t b/_templates/method-generator/new/DocumentViewModule.ejs.t new file mode 100644 index 000000000..d1a3b8fa8 --- /dev/null +++ b/_templates/method-generator/new/DocumentViewModule.ejs.t @@ -0,0 +1,24 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/modules/DocumentViewModule.java +after: // Hygen Generated Methods +--- +<% parameters = params === '' ? '' : h.androidParams(params, true) + ', ' + args = params === '' ? '' : ', ' + h.androidArgs(params) + returnVar = returnType === 'void' ? '' : h.androidReturnType(returnType) + ' field = ' +-%> + + @ReactMethod + public void <%= name %>(<%- parameters %>final Promise promise) { + getReactApplicationContext().runOnUiQueueThread(new Runnable() { + @Override + public void run() { + try { + <%= returnVar %>mDocumentViewInstance.<%= name %>(tag<%= args %>); + promise.resolve(<%= returnType === 'void' ? 'null' : 'field' %>); + } catch (Exception ex) { + promise.reject(ex); + } + } + }); + } diff --git a/_templates/method-generator/new/DocumentViewViewManagerjava.ejs.t b/_templates/method-generator/new/DocumentViewViewManagerjava.ejs.t new file mode 100644 index 000000000..193588ae3 --- /dev/null +++ b/_templates/method-generator/new/DocumentViewViewManagerjava.ejs.t @@ -0,0 +1,15 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/viewmanagers/DocumentViewViewManager.java +after: // Hygen Generated Methods +--- +<% parameters = params === '' ? '' : ', ' + h.androidParams(params, false) -%> + + public <%- h.androidReturnType(returnType) %> <%= name %>(int tag<%- parameters %>) throws PDFNetException { + DocumentView documentView = mDocumentViews.get(tag); + if (documentView != null) { + return documentView.<%= name %>(<%= h.androidArgs(params) %>); + } else { + throw new PDFNetException("", 0L, getName(), "<%= name %>", "Unable to find DocumentView."); + } + } diff --git a/_templates/method-generator/new/DocumentViewjava.ejs.t b/_templates/method-generator/new/DocumentViewjava.ejs.t new file mode 100644 index 000000000..2249c4aae --- /dev/null +++ b/_templates/method-generator/new/DocumentViewjava.ejs.t @@ -0,0 +1,9 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/views/DocumentView.java +after: // Hygen Generated Methods +--- + + public <%- h.androidReturnType(returnType) %> <%= name %>(<%- params === '' ? '' : h.androidParams(params, false) %>) { + + } diff --git a/_templates/method-generator/new/DocumentViewtsx.ejs.t b/_templates/method-generator/new/DocumentViewtsx.ejs.t new file mode 100644 index 000000000..9e57b5832 --- /dev/null +++ b/_templates/method-generator/new/DocumentViewtsx.ejs.t @@ -0,0 +1,21 @@ +--- +inject: true +to: src/DocumentView/DocumentView.tsx +after: // Hygen Generated Methods +--- +<% promiseType = returnType + if (promiseType === 'void') { + promiseType = 'Promise' + } else { + promiseType = 'Promise' + } + promiseType = promiseType.replace(/\bint\b|\bdouble\b/g, 'number'); + parameters = params.replace(/\bint\b|\bdouble\b/g, 'number'); +-%> + <%= name %> = (<%- parameters %>): <%- promiseType %> => { + const tag = findNodeHandle(this._viewerRef); + if (tag != null) { + return DocumentViewManager.<%= name %>(tag<%= params === '' ? '' : ', ' + h.androidArgs(params) %>); + } + return Promise.resolve(); + } diff --git a/_templates/method-generator/new/RNTPTDocumentViewManagerh.ejs.t b/_templates/method-generator/new/RNTPTDocumentViewManagerh.ejs.t new file mode 100644 index 000000000..e8e0dfeb4 --- /dev/null +++ b/_templates/method-generator/new/RNTPTDocumentViewManagerh.ejs.t @@ -0,0 +1,7 @@ +--- +inject: true +to: ios/RNTPTDocumentViewManager.h +after: Hygen Generated Methods +--- + +- (<%= h.iOSReturnType(returnType) %>)<%= name %>ForDocumentViewTag:(NSNumber *)tag<%= params === '' ? '' : ' ' + h.iOSParams(params) %>;<% -%> diff --git a/_templates/method-generator/new/RNTPTDocumentViewManagerm.ejs.t b/_templates/method-generator/new/RNTPTDocumentViewManagerm.ejs.t new file mode 100644 index 000000000..e5b677997 --- /dev/null +++ b/_templates/method-generator/new/RNTPTDocumentViewManagerm.ejs.t @@ -0,0 +1,15 @@ +--- +inject: true +to: ios/RNTPTDocumentViewManager.m +after: Hygen Generated Methods +--- +<% args = h.iOSArgs(params) -%> +- (<%= h.iOSReturnType(returnType) %>)<%= name %>ForDocumentViewTag:(NSNumber *)tag<%= params === '' ? '' : ' ' + h.iOSParams(params) %> +{ + RNTPTDocumentView *documentView = self.documentViews[tag]; + if (documentView) { + <%= returnType === 'void' ? '' : 'return ' %>[documentView <%= name %><%= params === '' ? '' : ':' + args.substring(args.indexOf(':') + 1) %>]; + } else { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Unable to get field for tag" userInfo:nil];<%= returnType === 'void' ? '' : '\n return nil;' %> + } +} diff --git a/_templates/method-generator/new/RNTPTDocumentViewModulem.ejs.t b/_templates/method-generator/new/RNTPTDocumentViewModulem.ejs.t new file mode 100644 index 000000000..d7c186bb4 --- /dev/null +++ b/_templates/method-generator/new/RNTPTDocumentViewModulem.ejs.t @@ -0,0 +1,27 @@ +--- +inject: true +to: ios/RNTPTDocumentViewModule.m +after: Hygen Generated Methods +--- +<% returnVar = h.iOSReturnType(returnType) + if (returnVar === 'void') { + returnVar = '' + } else if (!returnVar.endsWith('*')) { + returnVar = returnVar + ' result = ' + } else { + returnVar = returnVar + 'result = ' + } +-%> +RCT_REMAP_METHOD(<%= name %>, + <%= name %>ForDocumentViewTag:(nonnull NSNumber *)tag<%= params === '' ? '' : '\n ' + h.iOSParams(params, true) %> + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + @try { + <%= returnVar %>[[self documentViewManager] <%= name %>ForDocumentViewTag:tag<%= params === '' ? '' : ' ' + h.iOSArgs(params) %>]; + resolve(<%= returnType === 'void' ? 'nil' : 'result' %>); + } + @catch (NSException *exception) { + reject(@"<%= h.changeCase.snakeCase(name) %>", @"Failed to <%= h.changeCase.noCase(name) %>", [self errorFromException:exception]); + } +} diff --git a/_templates/method-generator/new/RNTPTDocumentViewh.ejs.t b/_templates/method-generator/new/RNTPTDocumentViewh.ejs.t new file mode 100644 index 000000000..acb649091 --- /dev/null +++ b/_templates/method-generator/new/RNTPTDocumentViewh.ejs.t @@ -0,0 +1,13 @@ +--- +inject: true +to: ios/RNTPTDocumentView.h +after: Hygen Generated Methods +--- +<% parameters = '' + if (params !== '') { + parameters = h.iOSParams(params) + // chopping off the parameter name of the first parameter to follow proper syntax + parameters = ':' + parameters.substring(parameters.indexOf(':') + 1) + } +-%> +- (<%= h.iOSReturnType(returnType) %>)<%= name %><%= parameters %>; diff --git a/_templates/method-generator/new/RNTPTDocumentViewm.ejs.t b/_templates/method-generator/new/RNTPTDocumentViewm.ejs.t new file mode 100644 index 000000000..29210076d --- /dev/null +++ b/_templates/method-generator/new/RNTPTDocumentViewm.ejs.t @@ -0,0 +1,17 @@ +--- +inject: true +to: ios/RNTPTDocumentView.m +after: Hygen Generated Props/Methods +--- +<% parameters = '' + if (params !== '') { + parameters = h.iOSParams(params) + // chopping off the parameter name of the first parameter to follow proper syntax + parameters = ':' + parameters.substring(parameters.indexOf(':') + 1) + } +-%> + +- (<%= h.iOSReturnType(returnType) %>)<%= name %><%= parameters %> +{ + +}<% -%> diff --git a/_templates/method-generator/new/index.js b/_templates/method-generator/new/index.js new file mode 100644 index 000000000..af4ce4ae1 --- /dev/null +++ b/_templates/method-generator/new/index.js @@ -0,0 +1,26 @@ +module.exports = { + prompt: ({ inquirer }) => { + // defining questions in arrays ensures all questions are asked before next prompt is executed + const questions = [ + { + type: 'input', + name: 'name', + message: 'Name of method?', + }, + { + type: 'input', + name: 'params', + message: 'Parameter list of React Native method (comma separated)? Use either int or double for number\n (ex: flag: boolean, page: int, options: { annotList: Array }, ...)\n', + }, + { + type: 'input', + name: 'returnType', + message: 'Return type of React Native method? Use either int or double for number\n (ex: void, boolean, int, { fieldName: string, fieldValue?: any }, ...)\n', + } + ] + + // returning the answers to the prompt + return inquirer + .prompt(questions) + }, +} diff --git a/_templates/prop-generator/new/DocumentViewJava.ejs.t b/_templates/prop-generator/new/DocumentViewJava.ejs.t new file mode 100644 index 000000000..d87d9a4b3 --- /dev/null +++ b/_templates/prop-generator/new/DocumentViewJava.ejs.t @@ -0,0 +1,8 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/views/DocumentView.java +after: // Hygen Generated Props +--- + public void set<%= h.changeCase.pascalCase(name) %>(<%= h.androidPropType(propType) %> <%= paramName %>) { + + } diff --git a/_templates/prop-generator/new/DocumentViewViewManagerJava.ejs.t b/_templates/prop-generator/new/DocumentViewViewManagerJava.ejs.t new file mode 100644 index 000000000..2ec86c5cc --- /dev/null +++ b/_templates/prop-generator/new/DocumentViewViewManagerJava.ejs.t @@ -0,0 +1,9 @@ +--- +inject: true +to: android/src/main/java/com/pdftron/reactnative/viewmanagers/DocumentViewViewManager.java +after: // Hygen Generated Props +--- + @ReactProp(name = "<%= name %>") + public void set<%= h.changeCase.pascalCase(name) %>(DocumentView documentView, <%= h.androidPropType(propType) %> <%= paramName %>) { + documentView.set<%= h.changeCase.pascalCase(name) %>(<%= paramName %>); + } diff --git a/_templates/prop-generator/new/DocumentViewtsx.ejs.t b/_templates/prop-generator/new/DocumentViewtsx.ejs.t new file mode 100644 index 000000000..bb353b00b --- /dev/null +++ b/_templates/prop-generator/new/DocumentViewtsx.ejs.t @@ -0,0 +1,16 @@ +--- +inject: true +to: src/DocumentView/DocumentView.tsx +after: // Hygen Generated Props +--- + +<% type = propType.trim() + if (type === 'oneOf' || type === 'arrayOf') { + type = type + '<' + configType + '>(' + configType + ')' + } else if (type === 'int' || type === 'double') { + type = 'PropTypes.number' + } else { + type = 'PropTypes.' + type + } +-%> + <%= name %>: <%- type %>,<% -%> diff --git a/_templates/prop-generator/new/RNTPTDocumentViewManager.ejs.t b/_templates/prop-generator/new/RNTPTDocumentViewManager.ejs.t new file mode 100644 index 000000000..5ed5cbca5 --- /dev/null +++ b/_templates/prop-generator/new/RNTPTDocumentViewManager.ejs.t @@ -0,0 +1,21 @@ +--- +inject: true +to: ios/RNTPTDocumentViewManager.m +after: // Hygen Generated Props +--- +<%# converting the React Native prop type into the corresponding iOS type as an argument to the RCTConvert function -%> +<% type = propType + if (type === 'bool') { + type = 'BOOL' + } else if (type === 'string' || type === 'oneOf') { + type = 'NSString' + } else if (type === 'arrayOf') { + type = 'NSArray' + } +-%> +RCT_CUSTOM_VIEW_PROPERTY(<%= name %>, <%= type %>, RNTPTDocumentView) +{ + if (json) { + view.<%= paramName %> = [RCTConvert <%= type %>:json]; + } +} diff --git a/_templates/prop-generator/new/RNTPTDocumentViewh.ejs.t b/_templates/prop-generator/new/RNTPTDocumentViewh.ejs.t new file mode 100644 index 000000000..f2a27a110 --- /dev/null +++ b/_templates/prop-generator/new/RNTPTDocumentViewh.ejs.t @@ -0,0 +1,18 @@ +--- +inject: true +to: ios/RNTPTDocumentView.h +after: // Hygen Generated Props +--- +<%# converting the React Native prop type into the corresponding iOS type, along with appropriate keywords -%> +<% type = propType + if (type === 'bool') { + type = '(nonatomic, assign) BOOL ' + } else if (type === 'string' || type === 'oneOf') { + type = '(nonatomic, copy, nullable) NSString *' + } else if (type === 'arrayOf') { + type = '(nonatomic, copy, nullable) NSArray ' + } else { + type = '(nonatomic, assign) ' + type + ' ' + } +-%> +@property <%- type %><%= name %>; <% -%> diff --git a/_templates/prop-generator/new/RNTPTDocumentViewm.ejs.t b/_templates/prop-generator/new/RNTPTDocumentViewm.ejs.t new file mode 100644 index 000000000..8f8194161 --- /dev/null +++ b/_templates/prop-generator/new/RNTPTDocumentViewm.ejs.t @@ -0,0 +1,20 @@ +--- +inject: true +to: ios/RNTPTDocumentView.m +after: Hygen Generated Props/Methods +--- +<%# converting the React Native prop type into the corresponding iOS type -%> +<% type = propType + if (type === 'bool') { + type = 'BOOL' + } else if (type === 'string' || type === 'oneOf') { + type = 'NSString *' + } else if (type === 'arrayOf') { + type = 'NSArray *' + } +-%> + +- (void)set<%= h.changeCase.pascalCase(name) %>:(<%= type %>)<%= paramName %> +{ + +}<% -%> diff --git a/_templates/prop-generator/new/index.js b/_templates/prop-generator/new/index.js new file mode 100644 index 000000000..9ff70175d --- /dev/null +++ b/_templates/prop-generator/new/index.js @@ -0,0 +1,43 @@ +module.exports = { + prompt: ({ inquirer }) => { + // defining questions in arrays ensures all questions are asked before next prompt is executed + const questions = [ + { + type: 'input', + name: 'name', + message: 'Name of prop?', + }, + { + type: 'input', + name: 'propType', + message: 'Type of prop? Choose from: bool, string, int, double, oneOf, arrayOf\n', + } + ] + + return inquirer + .prompt(questions) + .then(answers => { + // using the answers from the previous prompt to determine which questions to ask next + const propType = answers.propType.trim() + const questions = [ + { + type: 'input', + name: 'paramName', + message: 'Name of parameter?', + default: answers.name, + } + ] + + if (propType === 'oneOf' || propType === 'arrayOf') { + questions.unshift({ + type: 'input', + name: 'configType', + message: 'Name of the Config constant type for the ' + propType + '? (ex: Config.LayoutMode)', + }) + } + + // return the merged set of answers from the previous prompt and this prompt + return inquirer.prompt(questions).then(nextAnswers => Object.assign({}, answers, nextAnswers)) + }) + }, +} diff --git a/android/src/main/java/com/pdftron/reactnative/modules/DocumentViewModule.java b/android/src/main/java/com/pdftron/reactnative/modules/DocumentViewModule.java index 11aeca666..7134b5002 100644 --- a/android/src/main/java/com/pdftron/reactnative/modules/DocumentViewModule.java +++ b/android/src/main/java/com/pdftron/reactnative/modules/DocumentViewModule.java @@ -1455,6 +1455,8 @@ public void run() { }); } + // Hygen Generated Methods + @Override public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { mDocumentViewInstance.onActivityResult(requestCode, resultCode, data); diff --git a/android/src/main/java/com/pdftron/reactnative/utils/Constants.java b/android/src/main/java/com/pdftron/reactnative/utils/Constants.java index 70e64be40..cc1306230 100644 --- a/android/src/main/java/com/pdftron/reactnative/utils/Constants.java +++ b/android/src/main/java/com/pdftron/reactnative/utils/Constants.java @@ -32,6 +32,8 @@ public final class Constants { public static final String ON_SAVED_SIGNATURES_CHANGED = "onSavedSignaturesChanged"; public static final String ON_TOOLBAR_BUTTON_PRESS = "onToolbarButtonPress"; + // Hygen Generated Event Listeners + // BUTTONS public static final String BUTTON_TOOLS = "toolsButton"; public static final String BUTTON_SEARCH = "searchButton"; @@ -361,6 +363,8 @@ public final class Constants { public static final String KEY_CURRENT_TAB = "currentTab"; + // Hygen Generated Keys + // Color RGBA public static final String COLOR_RED = "red"; public static final String COLOR_GREEN = "green"; diff --git a/android/src/main/java/com/pdftron/reactnative/viewmanagers/DocumentViewViewManager.java b/android/src/main/java/com/pdftron/reactnative/viewmanagers/DocumentViewViewManager.java index faa419b71..ccf3b73c3 100644 --- a/android/src/main/java/com/pdftron/reactnative/viewmanagers/DocumentViewViewManager.java +++ b/android/src/main/java/com/pdftron/reactnative/viewmanagers/DocumentViewViewManager.java @@ -524,7 +524,9 @@ public void setHighlighterSmoothingEnabled(DocumentView documentView, boolean hi @ReactProp(name = "maxSignatureCount") public void setMaxSignatureCount(DocumentView documentView, int maxSignatureCount) { SignatureDialogFragment.MAX_SIGNATURES = maxSignatureCount; - } + } + + // Hygen Generated Props @ReactProp(name = "overrideToolbarButtonBehavior") public void setOverrideToolbarButtonBehavior(DocumentView documentView, @NonNull ReadableArray items) { @@ -1410,6 +1412,8 @@ public String getSavedSignatureJpgFolder(int tag) throws PDFNetException { } } + // Hygen Generated Methods + @Override public boolean needsCustomLayoutForChildren() { return true; diff --git a/android/src/main/java/com/pdftron/reactnative/views/DocumentView.java b/android/src/main/java/com/pdftron/reactnative/views/DocumentView.java index 86f4a4ac5..7ca52cf26 100644 --- a/android/src/main/java/com/pdftron/reactnative/views/DocumentView.java +++ b/android/src/main/java/com/pdftron/reactnative/views/DocumentView.java @@ -746,6 +746,8 @@ public void setCurrentToolbar(String toolbarTag) { } } + // Hygen Generated Props + public void setAnnotationToolbars(ReadableArray toolbars) { if (toolbars.size() == 0) { if (mPdfViewCtrlTabHostFragment != null) { @@ -3099,6 +3101,8 @@ public boolean onOpenDocError() { return true; } + // Hygen Generated Event Listeners + public void importBookmarkJson(String bookmarkJson) throws PDFNetException { PDFViewCtrl pdfViewCtrl = getPdfViewCtrl(); @@ -4809,6 +4813,8 @@ public String getSavedSignatureJpgFolder() { return ""; } + // Hygen Generated Methods + public void setSaveStateEnabled(boolean saveStateEnabled) { mSaveStateEnabled = saveStateEnabled; } diff --git a/ios/RNTPTDocumentView.h b/ios/RNTPTDocumentView.h index 6a4a34032..1c142f420 100644 --- a/ios/RNTPTDocumentView.h +++ b/ios/RNTPTDocumentView.h @@ -381,6 +381,8 @@ static NSString * const PTSignaturesManager_signatureDirectory = @"PTSignaturesM - (void)toolbarButtonPressed:(RNTPTDocumentView *)sender withKey:(NSString *)itemKey; +// Hygen Generated Event Listeners + @end @interface RNTPTDocumentView : UIView @@ -413,6 +415,8 @@ static NSString * const PTSignaturesManager_signatureDirectory = @"PTSignaturesM @property (nonatomic, assign) BOOL autoSaveEnabled; @property (nonatomic, assign) BOOL enableAntialiasing; +// Hygen Generated Props + @property (nonatomic, copy, nullable) NSString *password; @property (nonatomic, copy, nullable) NSString *document; @property (nonatomic, copy, nullable) NSString *source; @@ -717,6 +721,7 @@ static NSString * const PTSignaturesManager_signatureDirectory = @"PTSignaturesM -(NSString *)getSavedSignatureFolder; +// Hygen Generated Methods @end diff --git a/ios/RNTPTDocumentView.m b/ios/RNTPTDocumentView.m index add740a3b..3ff95dcfd 100644 --- a/ios/RNTPTDocumentView.m +++ b/ios/RNTPTDocumentView.m @@ -5984,6 +5984,8 @@ - (void)openThumbnailsView [self.currentDocumentViewController showThumbnailsController]; } +#pragma mark - Hygen Generated Props/Methods + @end #pragma mark - RNTPTThumbnailsViewController diff --git a/ios/RNTPTDocumentViewManager.h b/ios/RNTPTDocumentViewManager.h index 0980b529c..41841bd6d 100644 --- a/ios/RNTPTDocumentViewManager.h +++ b/ios/RNTPTDocumentViewManager.h @@ -195,4 +195,6 @@ - (NSString *)getSavedSignatureFolderForDocumentViewTag:(NSNumber *)tag; +#pragma mark - Hygen Generated Methods + @end diff --git a/ios/RNTPTDocumentViewManager.m b/ios/RNTPTDocumentViewManager.m index 35b7e8172..ab141c2fd 100644 --- a/ios/RNTPTDocumentViewManager.m +++ b/ios/RNTPTDocumentViewManager.m @@ -651,6 +651,8 @@ - (instancetype)init } } +// Hygen Generated Props + - (UIView *)view { @@ -977,6 +979,8 @@ - (void)toolbarButtonPressed:(RNTPTDocumentView *)sender withKey:(NSString *)ite } } +// Hygen Generated Event Listeners + #pragma mark - Methods - (void)setToolModeForDocumentViewTag:(NSNumber *)tag toolMode:(NSString *)toolMode @@ -1651,6 +1655,8 @@ - (NSString *)getSavedSignatureFolderForDocumentViewTag:(NSNumber *)tag } } +#pragma mark - Hygen Generated Methods + #pragma mark - Coordination - (NSArray *)convertScreenPointsToPagePointsForDocumentViewTag:(nonnull NSNumber *)tag points:(NSArray *)points diff --git a/ios/RNTPTDocumentViewModule.m b/ios/RNTPTDocumentViewModule.m index f9d37b734..c05704c3d 100644 --- a/ios/RNTPTDocumentViewModule.m +++ b/ios/RNTPTDocumentViewModule.m @@ -1408,4 +1408,6 @@ - (NSError *)errorFromException:(NSException *)exception } } +#pragma mark - Hygen Generated Methods + @end diff --git a/lib/src/DocumentView/DocumentView.js b/lib/src/DocumentView/DocumentView.js index 2df52a2c5..5a70bbc25 100644 --- a/lib/src/DocumentView/DocumentView.js +++ b/lib/src/DocumentView/DocumentView.js @@ -153,6 +153,7 @@ const propTypes = { maxSignatureCount: PropTypes.number, overrideToolbarButtonBehavior: arrayOf(Config.Buttons), onToolbarButtonPress: func(), + // Hygen Generated Props ...ViewPropTypes, }; /** @@ -424,6 +425,7 @@ export class DocumentView extends PureComponent { 'id': event.nativeEvent.id, }); } + // Hygen Generated Event Listeners } }; // Methods @@ -545,6 +547,7 @@ export class DocumentView extends PureComponent { } return Promise.resolve(); }; + // Hygen Generated Methods /** * note: this function exists for supporting the old version. It simply calls setValuesForFields. * diff --git a/package.json b/package.json index 6eb56db38..59598b90d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-native-pdftron", "title": "React Native Pdftron", - "version": "3.0.2-beta.113", + "version": "3.0.2-beta.114", "description": "React Native Pdftron", "main": "./lib/index.js", "typings": "index.ts", diff --git a/src/DocumentView/DocumentView.tsx b/src/DocumentView/DocumentView.tsx index 558571110..b38c2a493 100644 --- a/src/DocumentView/DocumentView.tsx +++ b/src/DocumentView/DocumentView.tsx @@ -162,6 +162,9 @@ const propTypes = { maxSignatureCount: PropTypes.number, overrideToolbarButtonBehavior: arrayOf(Config.Buttons), onToolbarButtonPress: func<(event: {id: string}) => void>(), + + // Hygen Generated Props + ...ViewPropTypes, }; @@ -420,6 +423,7 @@ export class DocumentView extends PureComponent { 'id': event.nativeEvent.id, }); } + // Hygen Generated Event Listeners } } @@ -564,6 +568,8 @@ export class DocumentView extends PureComponent { return Promise.resolve(); } + // Hygen Generated Methods + /** * note: this function exists for supporting the old version. It simply calls setValuesForFields. *