/
AppWrapper.js
104 lines (82 loc) · 2.28 KB
/
AppWrapper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
'use strict';
require('./browser-polyfills');
const React = require('react-native');
const {
AppRegistry,
StyleSheet,
Text,
View,
} = React;
const Elm = require('./elm');
const ReactComponents = require('./ReactComponents');
// Returns a `make` function that will patch the local elm runtime and
// replace the `render` and `update` functions in localRuntime.Native.VirtualDom
// with implementations that call `setState` on the `AppWrapper` component instance
function runtimePatcher(appWrapperInstance) {
function make(localRuntime) {
function render(state) {
console.log('rendering new state: ', state);
appWrapperInstance.setState({vdom: state});
return appWrapperInstance;
}
function updateAndReplace(elem, oldState, newState) {
return render(newState);
}
var VirtualDom = Elm.Native.VirtualDom.make(localRuntime);
localRuntime.Native.VirtualDom.values = {
...VirtualDom,
render: render,
updateAndReplace: updateAndReplace,
patchedForReactNative: true,
};
return Elm.Main.make(localRuntime);
}
return make;
}
const AppWrapper = React.createClass({
componentWillMount() {
Elm.fullscreen({make: runtimePatcher(this)});
},
getInitialState() {
return {vdom: null};
},
render() {
let vdom = this.state.vdom;
return React.createElement(View, {style: styles.container},
vDomToReactElement(vdom)
);
}
});
function getNested(obj, path) {
if (typeof(obj) !== 'object' || typeof(path) !== 'string') {
return undefined;
}
let pathComponents = path.split('.');
while (typeof(obj) === 'object') {
let p = pathComponents.shift();
obj = obj[p];
}
return obj;
}
function vDomToReactElement(vdomNode) {
if (!vdomNode) {
return undefined;
}
if (typeof(vdomNode.text) === 'string') {
return vdomNode.text;
}
let {tagName, properties, key} = vdomNode;
properties = {...properties, key};
let children = vdomNode.children || [];
children = children.map(vDomToReactElement);
let reactClass = getNested(ReactComponents, tagName);
return React.createElement(reactClass, properties, ...children);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
export default AppWrapper;