Version 0.1
Shuning Zhang ([email protected])
npm install --save reactgenie
The repo of reactgenie contains:
- index.ts
- modality-provider.tsx
- shared-counterStore.ts
- decorator.ts
Index provides a combined import of all functions and outer packages we needed.
Modality provider provides the definition and abstract implementation of another modality (in our case for example, it is voice interface).
Shared store provides a combined definition and way of using state (based on redux) using our implementation of reactgenie. Based on that, you could operate on the state and extend to another state more easily.
Decorator contains the decorator definition and implementation for the object under this framework, "GenieClass", and interface anchor point under this framework, "GenieClassInterface". Using GenieClass, we could collect the definition of different objects and parse voice input correspondingly into function calls when entering voice input. Using GenieClassInterface, we could collect pages developers wanted to navigate to, then a stack navigator containing all these pages with decorator would be generated for usage.
We highly recommend developers use react native / react js to develop their application and use redux to take control of their data and state. Under this framework, we also provided some demo applications for developers to refer to. (See ./example/
and corresponding sub-directory for more details)
For a normal application to be developed, developers should take care of the following things.
-
Design their interfaces with decorators (object and interface) like below, they should mark all the objects which may have correlation with the voice interface with
GenieClass
. Also, they should mark all the pages which they design to have navigation withGenieClassInterface
../example/CounterView.tsx
:export const CounterView = GenieClassInterface((counter: Counter) => `${counter.name} Counter`, "Counter")(CounterViewImpl)
./example/genie/counter.ts
:@GenieClass("A counter") export class Counter extends LampObject { public name: string; constructor({name}: {name: string}) { super(); this.name = name; } _getConstructorParams(): any { return { name: this.name } } // ... }
-
Implement your own class (object) with class definition and provide corresponding descriptors following the below format. Furthermore, you should give some simple examples as prompt to show how to transcript the voice input into concrete function calls.
// An example of descriptors static ClassDescriptor = new ClassDescriptor<Counter> ( "Counter", [ new FuncDescriptor("GetCounter", [ new ParamDescriptor("name", "string") ], "Counter", true), new FuncDescriptor("current", [], "Counter", true), new FuncDescriptor("getCount", [], "int", false), new FuncDescriptor("increment", [], "void", false), new FuncDescriptor("decrement", [], "void", false), ], [], Counter ) // An example of examples showing how to transcript voice input into concrete function call export const CounterExamples = [ { user_utterance: "increment", example_parsed: "Counter.current().increment()", }, { user_utterance: "decrement", example_parsed: "Counter.current().decrement()", }, { user_utterance: "what is the count", example_parsed: "Counter.current().getCount()", }, { user_utterance: "what is the count of potato", example_parsed: 'Counter.GetCounter(name: "potato").getCount()', }, { user_utterance: "what is the count of tomato", example_parsed: 'Counter.GetCounter(name: "tomato").getCount()', } ]
-
Wrap their interfaces with
ModalityProvider
orProvider
, thus they could easily add another modality (namely voice modality) based on auto generation.const App = () => { return ( <Provider store={store}> <ModalityProvider examples={CounterExamples} codexApiKey={"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"}> <div style={styles.container}> Potato Counter: <CounterView name={"potato"}/> </div> </ModalityProvider> </Provider> ); };
-
Import corresponding functions from
reactgenie
,redux
and other necessary package, then add corresponding configurations inpackage.json
"react-native-web": "~0.18.7", "react-redux": "^8.0.2", "reactgenie": "file:..", "redux": "^4.2.0" }, "devDependencies": { "@babel/core": "^7.8.6", "@babel/plugin-proposal-decorators": "^7.7.4", "@babel/plugin-transform-react-constant-elements": "^7.7.4", "@types/react": "~16.9.23", "@types/react-native": "~0.61.17",
-
Note that you should config to enable decorators.
// tsconfig.json "compilerOptions": { "experimentalDecorators": true, "allowSyntheticDefaultImports": true,
const counter = useSelector((state: any) => {
const result = genieSelector(`Counter.GetCounter(name: "${props.name}").getCount()`)(state)
console.log(`CounterView: ${result.value}`)
return result.value
});
title:
meaning: the name of class interface
type: string | (any) => string
You should wrap it on the view function.
export const CounterView = GenieClassInterface((counter: Counter) => `${counter.name} Counter`, "Counter")(CounterViewImpl)
examples:
meaning: the example sentences used for parsing
type: ExampleParse[], an array of parsing examples
codexApiKey:
meaning: the key used for codex api
type: string, a string which is the api for codex
children:
meaning: the child element of modality provider, used for ui building
type: React.ReactElement
const App = () => {
return (
<Provider store={store}>
<ModalityProvider
examples={CounterExamples}
codexApiKey={"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"}>
<div style={styles.container}>
Potato Counter:
<CounterView name={"potato"}/>
</div>
</ModalityProvider>
</Provider>
);
};
comment:
meaning: the extra note added to the genie class
type: string
@GenieClass("A counter")
export class Counter extends LampObject {
public name: string;
constructor({name}: {name: string}) {
super();
this.name = name;
}
null
@GenieClass("A counter")
export class Counter extends LampObject {
public name: string;
...
@NavigateFunction()
static GetCounter({name}: {name: string}): Counter {
return new Counter({name: name});
}
...
}