Add receiveCommand to the Java Delegate
Summary: Adding support for receiving commands and calling methods defined on the interface in c7ee38149d
Reviewed By: JoshuaGross
Differential Revision: D16434402
fbshipit-source-id: a539050a1a2b2a67f9ba7145ed789de700461589
This commit is contained in:
Родитель
4ab9da134c
Коммит
4eca2e226c
|
@ -11,6 +11,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
CommandTypeShape,
|
||||||
ComponentShape,
|
ComponentShape,
|
||||||
PropTypeShape,
|
PropTypeShape,
|
||||||
SchemaType,
|
SchemaType,
|
||||||
|
@ -26,9 +27,19 @@ package com.facebook.react.viewmanagers;
|
||||||
::_IMPORTS_::
|
::_IMPORTS_::
|
||||||
|
|
||||||
public class ::_CLASSNAME_::<T extends ::_EXTEND_CLASSES_::> {
|
public class ::_CLASSNAME_::<T extends ::_EXTEND_CLASSES_::> {
|
||||||
|
::_METHODS_::
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const propSetterTemplate = `
|
||||||
public void setProperty(::_INTERFACE_CLASSNAME_::<T> viewManager, T view, String propName, Object value) {
|
public void setProperty(::_INTERFACE_CLASSNAME_::<T> viewManager, T view, String propName, Object value) {
|
||||||
::_PROP_CASES_::
|
::_PROP_CASES_::
|
||||||
}
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const commandsTemplate = `
|
||||||
|
public void receiveCommand(::_INTERFACE_CLASSNAME_::<T> viewManager, T view, String commandName, ReadableArray args) {
|
||||||
|
::_COMMAND_CASES_::
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -105,6 +116,52 @@ function generatePropCasesString(
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCommandArgJavaType(param) {
|
||||||
|
switch (param.typeAnnotation.type) {
|
||||||
|
case 'BooleanTypeAnnotation':
|
||||||
|
return 'getBoolean';
|
||||||
|
case 'Int32TypeAnnotation':
|
||||||
|
return 'getInt';
|
||||||
|
default:
|
||||||
|
(param.typeAnnotation.type: empty);
|
||||||
|
throw new Error('Receieved invalid typeAnnotation');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCommandArguments(command: CommandTypeShape): string {
|
||||||
|
const commandArgs = command.typeAnnotation.params
|
||||||
|
.map((param, index) => {
|
||||||
|
const commandArgJavaType = getCommandArgJavaType(param);
|
||||||
|
|
||||||
|
return `args.${commandArgJavaType}(${index})`;
|
||||||
|
})
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
return `view, ${commandArgs}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateCommandCasesString(
|
||||||
|
component: ComponentShape,
|
||||||
|
componentName: string,
|
||||||
|
) {
|
||||||
|
if (component.commands.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const commandMethods = component.commands
|
||||||
|
.map(command => {
|
||||||
|
return `case "${command.name}":
|
||||||
|
viewManager.${toSafeJavaString(
|
||||||
|
command.name,
|
||||||
|
false,
|
||||||
|
)}(${getCommandArguments(command)});
|
||||||
|
break;`;
|
||||||
|
})
|
||||||
|
.join('\n' + ' ');
|
||||||
|
|
||||||
|
return commandMethods;
|
||||||
|
}
|
||||||
|
|
||||||
function getClassExtendString(component): string {
|
function getClassExtendString(component): string {
|
||||||
const extendString = component.extendsProps
|
const extendString = component.extendsProps
|
||||||
.map(extendProps => {
|
.map(extendProps => {
|
||||||
|
@ -127,6 +184,28 @@ function getClassExtendString(component): string {
|
||||||
return extendString;
|
return extendString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDelegateImports(component) {
|
||||||
|
const imports = getImports(component);
|
||||||
|
// The delegate needs ReadableArray for commands always.
|
||||||
|
// The interface doesn't always need it
|
||||||
|
if (component.commands.length > 0) {
|
||||||
|
imports.add('import com.facebook.react.bridge.ReadableArray;');
|
||||||
|
}
|
||||||
|
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateMethods(propsString, commandsString): string {
|
||||||
|
return [
|
||||||
|
propSetterTemplate.trim().replace('::_PROP_CASES_::', propsString),
|
||||||
|
commandsString != null
|
||||||
|
? commandsTemplate.trim().replace('::_COMMAND_CASES_::', commandsString)
|
||||||
|
: '',
|
||||||
|
]
|
||||||
|
.join('\n\n ')
|
||||||
|
.trimRight();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
generate(libraryName: string, schema: SchemaType): FilesOutput {
|
generate(libraryName: string, schema: SchemaType): FilesOutput {
|
||||||
const files = new Map();
|
const files = new Map();
|
||||||
|
@ -143,8 +222,12 @@ module.exports = {
|
||||||
const interfaceClassName = `${componentName}ViewManagerInterface`;
|
const interfaceClassName = `${componentName}ViewManagerInterface`;
|
||||||
const fileName = `${className}.java`;
|
const fileName = `${className}.java`;
|
||||||
|
|
||||||
const imports = getImports(component);
|
const imports = getDelegateImports(component);
|
||||||
const propsString = generatePropCasesString(component, componentName);
|
const propsString = generatePropCasesString(component, componentName);
|
||||||
|
const commandsString = generateCommandCasesString(
|
||||||
|
component,
|
||||||
|
componentName,
|
||||||
|
);
|
||||||
const extendString = getClassExtendString(component);
|
const extendString = getClassExtendString(component);
|
||||||
|
|
||||||
const replacedTemplate = template
|
const replacedTemplate = template
|
||||||
|
@ -155,9 +238,13 @@ module.exports = {
|
||||||
.join('\n'),
|
.join('\n'),
|
||||||
)
|
)
|
||||||
.replace(/::_CLASSNAME_::/g, className)
|
.replace(/::_CLASSNAME_::/g, className)
|
||||||
.replace(/::_INTERFACE_CLASSNAME_::/g, interfaceClassName)
|
|
||||||
.replace('::_EXTEND_CLASSES_::', extendString)
|
.replace('::_EXTEND_CLASSES_::', extendString)
|
||||||
.replace('::_PROP_CASES_::', propsString);
|
.replace('::_PROP_CASES_::', propsString)
|
||||||
|
.replace(
|
||||||
|
'::_METHODS_::',
|
||||||
|
generateMethods(propsString, commandsString),
|
||||||
|
)
|
||||||
|
.replace(/::_INTERFACE_CLASSNAME_::/g, interfaceClassName);
|
||||||
|
|
||||||
files.set(fileName, replacedTemplate);
|
files.set(fileName, replacedTemplate);
|
||||||
});
|
});
|
||||||
|
|
|
@ -124,11 +124,9 @@ function generateCommandsString(
|
||||||
) {
|
) {
|
||||||
return component.commands
|
return component.commands
|
||||||
.map(command => {
|
.map(command => {
|
||||||
const safeJavaName = toSafeJavaString(command.name);
|
const safeJavaName = toSafeJavaString(command.name, false);
|
||||||
const lowerJavaName =
|
|
||||||
safeJavaName[0].toLowerCase() + safeJavaName.slice(1);
|
|
||||||
|
|
||||||
return `void ${lowerJavaName}(${getCommandArguments(
|
return `void ${safeJavaName}(${getCommandArguments(
|
||||||
command,
|
command,
|
||||||
componentName,
|
componentName,
|
||||||
)});`;
|
)});`;
|
||||||
|
|
|
@ -16,11 +16,17 @@ function upperCaseFirst(inString: string): string {
|
||||||
return inString[0].toUpperCase() + inString.slice(1);
|
return inString[0].toUpperCase() + inString.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toSafeJavaString(input: string): string {
|
function toSafeJavaString(
|
||||||
return input
|
input: string,
|
||||||
.split('-')
|
shouldUpperCaseFirst?: boolean,
|
||||||
.map(upperCaseFirst)
|
): string {
|
||||||
.join('');
|
const parts = input.split('-');
|
||||||
|
|
||||||
|
if (shouldUpperCaseFirst === false) {
|
||||||
|
return parts.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.map(upperCaseFirst).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImports(component: ComponentShape): Set<string> {
|
function getImports(component: ComponentShape): Set<string> {
|
||||||
|
|
|
@ -88,11 +88,21 @@ Map {
|
||||||
package com.facebook.react.viewmanagers;
|
package com.facebook.react.viewmanagers;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
|
|
||||||
public class CommandNativeComponentViewManagerDelegate<T extends View> {
|
public class CommandNativeComponentViewManagerDelegate<T extends View> {
|
||||||
public void setProperty(CommandNativeComponentViewManagerInterface<T> viewManager, T view, String propName, Object value) {
|
public void setProperty(CommandNativeComponentViewManagerInterface<T> viewManager, T view, String propName, Object value) {
|
||||||
// No props
|
// No props
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void receiveCommand(CommandNativeComponentInterface<T> viewManager, T view, String commandName, ReadableArray args) {
|
||||||
|
case \\"hotspotUpdate\\":
|
||||||
|
viewManager.hotspotUpdate(view, args.getInt(0), args.getInt(1));
|
||||||
|
break;
|
||||||
|
case \\"scrollTo\\":
|
||||||
|
viewManager.scrollTo(view, args.getInt(0), args.getBoolean(1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
}
|
}
|
||||||
|
@ -104,6 +114,7 @@ Map {
|
||||||
package com.facebook.react.viewmanagers;
|
package com.facebook.react.viewmanagers;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
|
|
||||||
public class CommandNativeComponentViewManagerDelegate<T extends View> {
|
public class CommandNativeComponentViewManagerDelegate<T extends View> {
|
||||||
public void setProperty(CommandNativeComponentViewManagerInterface<T> viewManager, T view, String propName, Object value) {
|
public void setProperty(CommandNativeComponentViewManagerInterface<T> viewManager, T view, String propName, Object value) {
|
||||||
|
@ -113,6 +124,12 @@ public class CommandNativeComponentViewManagerDelegate<T extends View> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void receiveCommand(CommandNativeComponentInterface<T> viewManager, T view, String commandName, ReadableArray args) {
|
||||||
|
case \\"hotspotUpdate\\":
|
||||||
|
viewManager.hotspotUpdate(view, args.getInt(0), args.getInt(1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче