@makano/rew 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/bin/rew +1 -8
- package/lib/rew/cli/cli.js +48 -50
- package/lib/rew/cli/run.js +4 -11
- package/lib/rew/cli/utils.js +136 -51
- package/lib/rew/const/default.js +6 -1
- package/lib/rew/const/files.js +3 -9
- package/lib/rew/const/pre-exec.js +3 -0
- package/lib/rew/functions/import.js +4 -3
- package/lib/rew/functions/misc.js +5 -0
- package/lib/rew/functions/sleep.js +1 -1
- package/lib/rew/functions/stdout.js +7 -4
- package/lib/rew/functions/wait.js +11 -0
- package/lib/rew/modules/compiler.js +9 -7
- package/lib/rew/modules/context.js +1 -1
- package/lib/rew/modules/runtime.js +21 -2
- package/lib/rew/pkgs/conf.js +8 -1
- package/lib/rew/pkgs/rune.js +12 -6
- package/main.js +13 -0
- package/package.json +5 -6
- package/bin/ui +0 -0
- package/bin/ui_ws +0 -0
- package/bin/webkit_app +0 -0
- package/build.sh +0 -8
- package/cpp/ui.cpp +0 -217
- package/cpp/ui1.cpp +0 -101
- package/cpp/ui2.cpp +0 -105
- package/lib/rew/css/theme.css +0 -3
- package/lib/rew/html/ui.html +0 -18
- package/lib/rew/html/ui.js +0 -245
- package/lib/rew/pkgs/modules/ui/classes.js +0 -184
- package/lib/rew/pkgs/ui.js +0 -157
- package/meson.build +0 -13
package/cpp/ui2.cpp
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
#include <gtk/gtk.h>
|
2
|
-
#include <libwebsockets.h>
|
3
|
-
#include <json/json.h>
|
4
|
-
#include <iostream>
|
5
|
-
#include <string>
|
6
|
-
#include <map>
|
7
|
-
|
8
|
-
std::map<std::string, GtkWidget *> widgets;
|
9
|
-
|
10
|
-
static void on_button_clicked(GtkWidget *widget, gpointer data)
|
11
|
-
{
|
12
|
-
// Send event back to Node.js server
|
13
|
-
std::string id = static_cast<char *>(data);
|
14
|
-
std::string message = "{\"event\": \"buttonClicked\", \"id\": \"" + id + "\"}";
|
15
|
-
lws_write(static_cast<lws *>(data), (unsigned char *)message.c_str(), message.length(), LWS_WRITE_TEXT);
|
16
|
-
}
|
17
|
-
|
18
|
-
static int callback_websocket(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
|
19
|
-
{
|
20
|
-
switch (reason)
|
21
|
-
{
|
22
|
-
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
23
|
-
std::cout << "Connected to server" << std::endl;
|
24
|
-
break;
|
25
|
-
case LWS_CALLBACK_CLIENT_RECEIVE:
|
26
|
-
{
|
27
|
-
std::string message(static_cast<char *>(in), len);
|
28
|
-
Json::CharReaderBuilder rbuilder;
|
29
|
-
Json::Value root;
|
30
|
-
std::string errors;
|
31
|
-
|
32
|
-
std::istringstream s(message);
|
33
|
-
std::string doc;
|
34
|
-
std::getline(s, doc);
|
35
|
-
std::istringstream ss(doc);
|
36
|
-
if (Json::parseFromStream(rbuilder, ss, &root, &errors))
|
37
|
-
{
|
38
|
-
std::string action = root["action"].asString();
|
39
|
-
|
40
|
-
if (action == "createButton")
|
41
|
-
{
|
42
|
-
GtkWidget *button = gtk_button_new_with_label(root["label"].asString().c_str());
|
43
|
-
g_signal_connect(button, "clicked", G_CALLBACK(on_button_clicked), strdup(root["id"].asString().c_str()));
|
44
|
-
widgets[root["id"].asString()] = button;
|
45
|
-
gtk_container_add(GTK_CONTAINER(gtk_window_new(GTK_WINDOW_TOPLEVEL)), button);
|
46
|
-
gtk_widget_show_all(button);
|
47
|
-
}
|
48
|
-
}
|
49
|
-
break;
|
50
|
-
}
|
51
|
-
case LWS_CALLBACK_CLIENT_CLOSED:
|
52
|
-
std::cout << "Disconnected from server" << std::endl;
|
53
|
-
break;
|
54
|
-
default:
|
55
|
-
break;
|
56
|
-
}
|
57
|
-
return 0;
|
58
|
-
}
|
59
|
-
|
60
|
-
static const struct lws_protocols protocols[] = {
|
61
|
-
{
|
62
|
-
"example-protocol",
|
63
|
-
callback_websocket,
|
64
|
-
0,
|
65
|
-
1024,
|
66
|
-
},
|
67
|
-
{NULL, NULL, 0, 0}};
|
68
|
-
|
69
|
-
int main(int argc, char **argv)
|
70
|
-
{
|
71
|
-
std::cout << "Starting" << std::endl;
|
72
|
-
if (argc != 2)
|
73
|
-
{
|
74
|
-
std::cerr << "Usage: " << argv[0] << " <WebSocket server URI>" << std::endl;
|
75
|
-
return 1;
|
76
|
-
}
|
77
|
-
|
78
|
-
gtk_init(&argc, &argv);
|
79
|
-
|
80
|
-
struct lws_context_creation_info info;
|
81
|
-
memset(&info, 0, sizeof info);
|
82
|
-
info.port = CONTEXT_PORT_NO_LISTEN;
|
83
|
-
info.protocols = protocols;
|
84
|
-
|
85
|
-
struct lws_context *context = lws_create_context(&info);
|
86
|
-
|
87
|
-
struct lws_client_connect_info ccinfo = {0};
|
88
|
-
ccinfo.context = context;
|
89
|
-
ccinfo.address = argv[1];
|
90
|
-
ccinfo.port = 8080;
|
91
|
-
ccinfo.path = "/";
|
92
|
-
ccinfo.host = lws_canonical_hostname(context);
|
93
|
-
ccinfo.origin = "origin";
|
94
|
-
ccinfo.protocol = protocols[0].name;
|
95
|
-
|
96
|
-
struct lws *wsi = lws_client_connect_via_info(&ccinfo);
|
97
|
-
|
98
|
-
while (lws_service(context, 1000) >= 0)
|
99
|
-
{
|
100
|
-
gtk_main_iteration_do(false);
|
101
|
-
}
|
102
|
-
|
103
|
-
lws_context_destroy(context);
|
104
|
-
return 0;
|
105
|
-
}
|
package/lib/rew/css/theme.css
DELETED
package/lib/rew/html/ui.html
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html lang="en">
|
3
|
-
<head>
|
4
|
-
<meta charset="UTF-8" />
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6
|
-
<title>$OPTIONS(title)</title>
|
7
|
-
|
8
|
-
<style>
|
9
|
-
/* $OPTIONS(style) */
|
10
|
-
</style>
|
11
|
-
|
12
|
-
<script>
|
13
|
-
window.onerror = () => alert('ERror');
|
14
|
-
</script>
|
15
|
-
</head>
|
16
|
-
|
17
|
-
<body></body>
|
18
|
-
</html>
|
package/lib/rew/html/ui.js
DELETED
@@ -1,245 +0,0 @@
|
|
1
|
-
try {
|
2
|
-
window.execContext = $OPTIONS(json.execContext);
|
3
|
-
} catch (e) {
|
4
|
-
window.execContext = {};
|
5
|
-
}
|
6
|
-
|
7
|
-
try {
|
8
|
-
window.exec = $OPTIONS(exec);
|
9
|
-
} catch (e) {
|
10
|
-
window.exec = function () {};
|
11
|
-
}
|
12
|
-
|
13
|
-
const DOM = [];
|
14
|
-
|
15
|
-
const findInDom = (id) => DOM.find((el) => el.widgetOptions.uuid == id) || DOM.find((el) => el.id == id);
|
16
|
-
|
17
|
-
const parseStyleValue = (val) => val;
|
18
|
-
|
19
|
-
const addTo = (el, parent) => {
|
20
|
-
if (parent == 'null') {
|
21
|
-
document.body.appendChild(el);
|
22
|
-
} else {
|
23
|
-
findInDom(parent).appendChild(el);
|
24
|
-
}
|
25
|
-
};
|
26
|
-
|
27
|
-
const initElement = (el, options, update = false) => {
|
28
|
-
if (el.widgetOptions) {
|
29
|
-
if (el.widgetOptions.style) {
|
30
|
-
for (let i in options.style) {
|
31
|
-
el.style.removeProperty(i, el.widgetOptions.style[i]);
|
32
|
-
}
|
33
|
-
}
|
34
|
-
if (el.widgetOptions.attr) {
|
35
|
-
for (let i in el.widgetOptions.attr) {
|
36
|
-
el.removeAttribute(i);
|
37
|
-
}
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
|
-
el.widgetOptions = options;
|
42
|
-
el.id = options.id;
|
43
|
-
el.textContent = options.data.text;
|
44
|
-
|
45
|
-
if (options.style) {
|
46
|
-
for (let i in options.style) {
|
47
|
-
el.style.setProperty(i, options.style[i]);
|
48
|
-
}
|
49
|
-
}
|
50
|
-
|
51
|
-
if (options.attr) {
|
52
|
-
for (let i in options.attr) {
|
53
|
-
el.setAttribute(i, options.attr[i]);
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
if (options.children.length) {
|
58
|
-
options.children.forEach((option) => {
|
59
|
-
option.parent = options.uuid;
|
60
|
-
if (update) updateElement(findInDom(option.uuid), option);
|
61
|
-
else createElement(option);
|
62
|
-
});
|
63
|
-
}
|
64
|
-
|
65
|
-
if (options.parent) {
|
66
|
-
addTo(el, options.parent);
|
67
|
-
}
|
68
|
-
};
|
69
|
-
|
70
|
-
const updateElement = (el, options) => {
|
71
|
-
if (!el) return;
|
72
|
-
initElement(el, options, true);
|
73
|
-
return el;
|
74
|
-
};
|
75
|
-
|
76
|
-
const events = [
|
77
|
-
'click',
|
78
|
-
'dblclick',
|
79
|
-
'mousedown',
|
80
|
-
'mouseup',
|
81
|
-
'mouseover',
|
82
|
-
'mouseout',
|
83
|
-
'mousemove',
|
84
|
-
'mouseenter',
|
85
|
-
'mouseleave',
|
86
|
-
'keydown',
|
87
|
-
'keypress',
|
88
|
-
'keyup',
|
89
|
-
'change',
|
90
|
-
'input',
|
91
|
-
'submit',
|
92
|
-
'focus',
|
93
|
-
'blur',
|
94
|
-
'copy',
|
95
|
-
'cut',
|
96
|
-
'paste',
|
97
|
-
'scroll',
|
98
|
-
'wheel',
|
99
|
-
'resize',
|
100
|
-
'contextmenu',
|
101
|
-
'drag',
|
102
|
-
'dragstart',
|
103
|
-
'dragend',
|
104
|
-
'dragenter',
|
105
|
-
'dragleave',
|
106
|
-
'dragover',
|
107
|
-
'drop',
|
108
|
-
'error',
|
109
|
-
'load',
|
110
|
-
'abort',
|
111
|
-
];
|
112
|
-
const handleListeners = (el) => {
|
113
|
-
events.forEach((event) => {
|
114
|
-
el.addEventListener(event, (e) => {
|
115
|
-
sendData({
|
116
|
-
action: 'hook:eventTrigger',
|
117
|
-
data: {
|
118
|
-
rid: 'event_trigger',
|
119
|
-
object: {
|
120
|
-
uuid: el.widgetOptions.uuid,
|
121
|
-
event,
|
122
|
-
data: {
|
123
|
-
mouse: { x: e.clientX, y: e.clientY },
|
124
|
-
key: { code: e.keyCode, key: e.key },
|
125
|
-
},
|
126
|
-
},
|
127
|
-
},
|
128
|
-
});
|
129
|
-
});
|
130
|
-
});
|
131
|
-
};
|
132
|
-
|
133
|
-
function eventHandlerFunction({ uuid, hookID, event }) {
|
134
|
-
return function (e) {
|
135
|
-
sendData({
|
136
|
-
action: 'hook:event_' + event,
|
137
|
-
data: {
|
138
|
-
rid: hookID,
|
139
|
-
object: {
|
140
|
-
uuid,
|
141
|
-
event,
|
142
|
-
data: {
|
143
|
-
mouse: { x: e.clientX, y: e.clientY },
|
144
|
-
key: { code: e.keyCode, key: e.key },
|
145
|
-
},
|
146
|
-
},
|
147
|
-
},
|
148
|
-
});
|
149
|
-
};
|
150
|
-
}
|
151
|
-
|
152
|
-
const createElement = (options) => {
|
153
|
-
const el = document.createElement(options.element);
|
154
|
-
DOM.push(el);
|
155
|
-
initElement(el, options);
|
156
|
-
return el;
|
157
|
-
};
|
158
|
-
|
159
|
-
const stringifyJSON = (json) => {
|
160
|
-
try {
|
161
|
-
return JSON.stringify(json, null, 4);
|
162
|
-
} catch (e) {
|
163
|
-
return json.toString();
|
164
|
-
}
|
165
|
-
};
|
166
|
-
|
167
|
-
const log = (...strings) => {
|
168
|
-
window.webkit.messageHandlers.external.postMessage(
|
169
|
-
JSON.stringify(
|
170
|
-
{
|
171
|
-
action: 'log',
|
172
|
-
data: strings
|
173
|
-
.map((r) => (typeof r == 'object' ? stringifyJSON(r) : `${r.toString()}`))
|
174
|
-
// .map((i) => i.replace(/\"/g, '\\\\"').replace(/\n/g, "\\\\n"))
|
175
|
-
.join('\n'),
|
176
|
-
},
|
177
|
-
null,
|
178
|
-
4,
|
179
|
-
),
|
180
|
-
);
|
181
|
-
};
|
182
|
-
|
183
|
-
const sendData = (data) => {
|
184
|
-
log('RESPONSE::' + stringifyJSON(data));
|
185
|
-
};
|
186
|
-
|
187
|
-
function process_data(data) {
|
188
|
-
return JSON.parse(data);
|
189
|
-
}
|
190
|
-
|
191
|
-
window.recieveMessage = (data) => {
|
192
|
-
const edata = data;
|
193
|
-
if (edata.action == 'eventListen') {
|
194
|
-
const el = findInDom(edata.data.uuid);
|
195
|
-
if (el) {
|
196
|
-
el.addEventListener(edata.data.event, eventHandlerFunction(edata.data));
|
197
|
-
}
|
198
|
-
} else if (edata.action == 'createElement') {
|
199
|
-
const options = edata.data;
|
200
|
-
try {
|
201
|
-
createElement(options);
|
202
|
-
} catch (e) {
|
203
|
-
log(e.toString());
|
204
|
-
}
|
205
|
-
} else if (edata.action == 'addStyleSheet') {
|
206
|
-
const style = document.createElement('style');
|
207
|
-
style.textContent = edata.data;
|
208
|
-
document.head.appendChild(style);
|
209
|
-
} else if (edata.action == 'updateElement') {
|
210
|
-
const options = edata.data;
|
211
|
-
try {
|
212
|
-
updateElement(findInDom(options.uuid), options);
|
213
|
-
} catch (e) {
|
214
|
-
log(e.toString());
|
215
|
-
}
|
216
|
-
} else if (edata.action == 'findElement') {
|
217
|
-
const id = edata.data.id;
|
218
|
-
const rid = edata.data.rid;
|
219
|
-
try {
|
220
|
-
sendData({
|
221
|
-
action: 'hook:findElement',
|
222
|
-
data: { rid, object: findInDom(id)?.widgetOptions },
|
223
|
-
});
|
224
|
-
} catch (e) {
|
225
|
-
log(e.toString());
|
226
|
-
}
|
227
|
-
} else if (edata.action == 'message') {
|
228
|
-
window.dispatchEvent(
|
229
|
-
new CustomEvent('message', {
|
230
|
-
detail: edata.data,
|
231
|
-
}),
|
232
|
-
);
|
233
|
-
}
|
234
|
-
};
|
235
|
-
|
236
|
-
window.addEventListener('load', () => {
|
237
|
-
window.exec({
|
238
|
-
...window.execContext,
|
239
|
-
window,
|
240
|
-
log,
|
241
|
-
send: (data) => sendData({ action: 'message', data }),
|
242
|
-
onRecieve: (cb) => window.addEventListener('message', (e) => cb(e.detail || {})),
|
243
|
-
});
|
244
|
-
log('SETUP::READY');
|
245
|
-
});
|
@@ -1,184 +0,0 @@
|
|
1
|
-
const emitter = require('../../../functions/emitter');
|
2
|
-
const { struct } = require('../../../models/struct');
|
3
|
-
const { generateRandomID } = require('../../../functions/id');
|
4
|
-
|
5
|
-
module.exports.uiClasses = (context, options, send, recieve, hook, rmHook) => {
|
6
|
-
const _sanitizeOptions = (options) => {
|
7
|
-
return {
|
8
|
-
...options,
|
9
|
-
children: options.children.map((i) => i.options),
|
10
|
-
};
|
11
|
-
};
|
12
|
-
const RemWidgetOptions = struct({
|
13
|
-
element: 'div',
|
14
|
-
class: '',
|
15
|
-
attr: {},
|
16
|
-
id: '',
|
17
|
-
data: {
|
18
|
-
text: '',
|
19
|
-
},
|
20
|
-
children: [],
|
21
|
-
uuid: '',
|
22
|
-
parent: '!any',
|
23
|
-
style: {},
|
24
|
-
});
|
25
|
-
|
26
|
-
const CreatedElements = [];
|
27
|
-
|
28
|
-
class RewWidget {
|
29
|
-
_emitter = emitter();
|
30
|
-
on(event, callback) {
|
31
|
-
const hookID = this.uuid + '_' + generateRandomID(4);
|
32
|
-
this._emitter.on(event, callback, { hookID });
|
33
|
-
hook(
|
34
|
-
hookID,
|
35
|
-
'event_' + event,
|
36
|
-
(data) => {
|
37
|
-
this.emit(event, data);
|
38
|
-
},
|
39
|
-
false,
|
40
|
-
);
|
41
|
-
send({ action: 'eventListen', data: { uuid: this.uuid, event, hookID } });
|
42
|
-
return this;
|
43
|
-
}
|
44
|
-
off(event, callback) {
|
45
|
-
this._emitter.off(event, callback, (e) => rmHook(e.hookID));
|
46
|
-
return this;
|
47
|
-
}
|
48
|
-
emit(event, callback) {
|
49
|
-
this._emitter.emit(event, callback);
|
50
|
-
return this;
|
51
|
-
}
|
52
|
-
|
53
|
-
options = RemWidgetOptions();
|
54
|
-
constructor(options = RemWidgetOptions()) {
|
55
|
-
const config = RemWidgetOptions(options);
|
56
|
-
config.uuid = generateRandomID();
|
57
|
-
this.options = config;
|
58
|
-
this.options.children.forEach((child) => (child.parent = this));
|
59
|
-
this.init();
|
60
|
-
CreatedElements.push(this);
|
61
|
-
}
|
62
|
-
|
63
|
-
init() {
|
64
|
-
send({ action: 'createElement', data: _sanitizeOptions(this.options) });
|
65
|
-
}
|
66
|
-
|
67
|
-
parent = null;
|
68
|
-
|
69
|
-
get uuid() {
|
70
|
-
return this.options.uuid;
|
71
|
-
}
|
72
|
-
|
73
|
-
get id() {
|
74
|
-
return this.options.id;
|
75
|
-
}
|
76
|
-
|
77
|
-
get children() {
|
78
|
-
return this.options.children;
|
79
|
-
}
|
80
|
-
|
81
|
-
find(id, recursive = true) {
|
82
|
-
let childFound = this.children.find((e) => e.id == id) || this.children.find((e) => e.uuid == id);
|
83
|
-
if (childFound) return childFound;
|
84
|
-
else if (!recursive) return null;
|
85
|
-
for (let child of this.children) {
|
86
|
-
let subchild = child.find(id);
|
87
|
-
if (subchild) {
|
88
|
-
return subchild;
|
89
|
-
}
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
update() {
|
94
|
-
send({ action: 'updateElement', data: _sanitizeOptions(this.options) });
|
95
|
-
return this;
|
96
|
-
}
|
97
|
-
|
98
|
-
text(text) {
|
99
|
-
this.options.data.text = text;
|
100
|
-
return this.update();
|
101
|
-
}
|
102
|
-
|
103
|
-
data(key, value) {
|
104
|
-
if (!value) return this.options.data[key];
|
105
|
-
this.options.data[key] = value;
|
106
|
-
return this.update();
|
107
|
-
}
|
108
|
-
|
109
|
-
attr(attr, reset = false) {
|
110
|
-
if (reset) this.options.attr = attr;
|
111
|
-
else this.options.attr = { ...this.options.attr, ...attr };
|
112
|
-
return this.update();
|
113
|
-
}
|
114
|
-
|
115
|
-
style(style, reset = false) {
|
116
|
-
if (reset) this.options.style = style;
|
117
|
-
else this.options.style = { ...this.options.style, ...style };
|
118
|
-
return this.update();
|
119
|
-
}
|
120
|
-
|
121
|
-
add(child) {
|
122
|
-
this.options.children.push(child);
|
123
|
-
return this.update();
|
124
|
-
}
|
125
|
-
|
126
|
-
remove(childId, recursive = true) {
|
127
|
-
const child = typeof childId == 'string' ? this.find(childId, recursive) : childId;
|
128
|
-
if (!child) return this;
|
129
|
-
if (recursive && child.parent !== this) {
|
130
|
-
child.parent.remove(child);
|
131
|
-
} else {
|
132
|
-
this.options.children.splice(this.options.children.indexOf(child), 1);
|
133
|
-
this.update();
|
134
|
-
}
|
135
|
-
return this;
|
136
|
-
}
|
137
|
-
}
|
138
|
-
|
139
|
-
class RewTextWidget extends RewWidget {
|
140
|
-
constructor(text = '', options = RemWidgetOptions({})) {
|
141
|
-
super({
|
142
|
-
...options,
|
143
|
-
data: { ...options.data, text },
|
144
|
-
});
|
145
|
-
}
|
146
|
-
}
|
147
|
-
|
148
|
-
class StyleSheet {
|
149
|
-
constructor(css = '') {
|
150
|
-
send({ action: 'addStyleSheet', data: css });
|
151
|
-
}
|
152
|
-
}
|
153
|
-
|
154
|
-
function findElement(id) {
|
155
|
-
return new Promise((r) => {
|
156
|
-
const rid = generateRandomID();
|
157
|
-
hook(rid, 'findElement', (data) => {
|
158
|
-
r(CreatedElements.find((e) => e.uuid == data.uuid) || data);
|
159
|
-
});
|
160
|
-
send({ action: 'findElement', data: { id, rid } });
|
161
|
-
});
|
162
|
-
}
|
163
|
-
|
164
|
-
// hook('event_trigger', 'eventTrigger', (data) => {
|
165
|
-
// const el = CreatedElements.find(e => e.uuid = data.uuid);
|
166
|
-
// if(el){
|
167
|
-
// el.emit(data.event, data.data);
|
168
|
-
// }
|
169
|
-
// }, false);
|
170
|
-
|
171
|
-
const Transmitter = {
|
172
|
-
send: (data) => send({ action: 'message', data }),
|
173
|
-
recieve: (cb) => recieve((data) => cb(data.data)),
|
174
|
-
};
|
175
|
-
|
176
|
-
return {
|
177
|
-
Widget: RewWidget,
|
178
|
-
Text: RewTextWidget,
|
179
|
-
WidgetOptions: RemWidgetOptions,
|
180
|
-
findElement,
|
181
|
-
StyleSheet: StyleSheet,
|
182
|
-
Transmitter,
|
183
|
-
};
|
184
|
-
};
|
package/lib/rew/pkgs/ui.js
DELETED
@@ -1,157 +0,0 @@
|
|
1
|
-
const path = require('path');
|
2
|
-
const { spawn, exec } = require('child_process');
|
3
|
-
const fs = require('fs');
|
4
|
-
const { uiClasses } = require('./modules/ui/classes');
|
5
|
-
const { generateRandomID } = require('../functions/id');
|
6
|
-
const { THEME_PATH } = require('../const/files');
|
7
|
-
const readline = require('readline');
|
8
|
-
const emitter = require('../functions/emitter');
|
9
|
-
|
10
|
-
const BIN_PATH = path.resolve(__dirname, '../../../bin/ui');
|
11
|
-
const HTML_STRING = fs.readFileSync(path.resolve(__dirname, '../html/ui.html'), { encoding: 'utf-8' });
|
12
|
-
const JS_STRING = fs.readFileSync(path.resolve(__dirname, '../html/ui.js'), {
|
13
|
-
encoding: 'utf-8',
|
14
|
-
});
|
15
|
-
|
16
|
-
const replaceString = (string, options) =>
|
17
|
-
string.replace(/\$OPTIONS\(([^)]+)\)/g, (_, n) =>
|
18
|
-
n.startsWith('json.') ? JSON.stringify(options[n.split('json.')[1]] || '{}') : options[n] || _,
|
19
|
-
);
|
20
|
-
|
21
|
-
const defaultOptions = {
|
22
|
-
title: 'Title',
|
23
|
-
onExit: () => process.exit(),
|
24
|
-
style: '',
|
25
|
-
stylePath: THEME_PATH,
|
26
|
-
exec: () => {},
|
27
|
-
execContext: {},
|
28
|
-
};
|
29
|
-
|
30
|
-
module.exports = (context) => ({
|
31
|
-
start: (o = {}) => {
|
32
|
-
const options = {
|
33
|
-
...defaultOptions,
|
34
|
-
...o,
|
35
|
-
};
|
36
|
-
|
37
|
-
const hookedSocketListeners = {};
|
38
|
-
|
39
|
-
const runId = generateRandomID();
|
40
|
-
const tmpFile = '/tmp/' + runId + '.ruw.ui.socket';
|
41
|
-
|
42
|
-
options.runId = runId;
|
43
|
-
|
44
|
-
if (fs.existsSync(options.stylePath)) options.style = fs.readFileSync(options.stylePath, { encoding: 'utf-8' }) + '\n' + options.style;
|
45
|
-
|
46
|
-
options.style = ' */\n' + options.style + '\n/* ';
|
47
|
-
|
48
|
-
const HTML = replaceString(HTML_STRING, options);
|
49
|
-
const JS = replaceString(JS_STRING, options);
|
50
|
-
|
51
|
-
/**
|
52
|
-
* Queue for future writes
|
53
|
-
* @type {string[]}
|
54
|
-
* */
|
55
|
-
const queue = [];
|
56
|
-
|
57
|
-
const send = (data) => {
|
58
|
-
const content = fs.readFileSync(tmpFile, { encoding: 'utf-8' });
|
59
|
-
if (content) {
|
60
|
-
queue.push(data);
|
61
|
-
} else {
|
62
|
-
fs.writeFileSync(tmpFile, typeof data !== 'string' ? JSON.stringify(data) : data);
|
63
|
-
}
|
64
|
-
};
|
65
|
-
|
66
|
-
const sendEvent = (data) => {
|
67
|
-
send({
|
68
|
-
action: 'JS',
|
69
|
-
data: `window.recieveMessage(${JSON.stringify(data)})`,
|
70
|
-
});
|
71
|
-
};
|
72
|
-
|
73
|
-
const g_emitter = emitter();
|
74
|
-
|
75
|
-
const recieve = (data) => {
|
76
|
-
g_emitter.emit('recieve', data);
|
77
|
-
};
|
78
|
-
|
79
|
-
const rl = readline.createInterface({
|
80
|
-
input: process.stdin,
|
81
|
-
output: process.stdout,
|
82
|
-
});
|
83
|
-
|
84
|
-
rl.question('', () => {});
|
85
|
-
|
86
|
-
fs.writeFileSync(tmpFile, '');
|
87
|
-
|
88
|
-
fs.watch(tmpFile, { encoding: 'utf-8' }).on('change', () => {
|
89
|
-
if (queue.length) {
|
90
|
-
send(queue.pop());
|
91
|
-
}
|
92
|
-
});
|
93
|
-
|
94
|
-
const p = spawn(options.bin || BIN_PATH, [runId]);
|
95
|
-
|
96
|
-
p.on('close', (code) => {
|
97
|
-
rl.close();
|
98
|
-
options.onExit(code);
|
99
|
-
});
|
100
|
-
|
101
|
-
process.on('beforeExit', () => {
|
102
|
-
p.kill();
|
103
|
-
fs.unlinkSync(tmpFile);
|
104
|
-
});
|
105
|
-
|
106
|
-
g_emitter.on('recieve', (edata) => {
|
107
|
-
if (edata.action.startsWith('hook:')) {
|
108
|
-
const hook = hookedSocketListeners[edata.data.rid];
|
109
|
-
const type = edata.action.split('hook:')[1];
|
110
|
-
if (hook && hook.type == type) {
|
111
|
-
hookedSocketListeners[edata.data.rid].cb(edata.data.object);
|
112
|
-
if (hook.once) delete hookedSocketListeners[edata.data.rid];
|
113
|
-
}
|
114
|
-
}
|
115
|
-
});
|
116
|
-
|
117
|
-
return new Promise((r) => {
|
118
|
-
p.stdout.on('data', (data) => {
|
119
|
-
if (data.toString().startsWith('RESPONSE::')) {
|
120
|
-
const d = data.toString().split('RESPONSE::')[1];
|
121
|
-
const jd = JSON.parse(d);
|
122
|
-
recieve(jd);
|
123
|
-
} else if (data.toString().trim().endsWith('SETUP::READY')) {
|
124
|
-
console.log('READY');
|
125
|
-
r(
|
126
|
-
uiClasses(
|
127
|
-
context,
|
128
|
-
options,
|
129
|
-
sendEvent,
|
130
|
-
(cb) => {
|
131
|
-
g_emitter.on('recieve', cb);
|
132
|
-
},
|
133
|
-
(rid, type, cb, once = true) => {
|
134
|
-
// Add hook
|
135
|
-
hookedSocketListeners[rid] = { type, cb, once };
|
136
|
-
},
|
137
|
-
(rid) => {
|
138
|
-
// Remove hook
|
139
|
-
delete hookedSocketListeners[rid];
|
140
|
-
},
|
141
|
-
),
|
142
|
-
);
|
143
|
-
} else if (data.toString().endsWith('SETUP::HTML')) {
|
144
|
-
send({ action: 'JS2', data: JS, isSetup: true });
|
145
|
-
} else if (data.toString() == 'INIT::READY') {
|
146
|
-
send({ action: 'HTML', data: HTML });
|
147
|
-
} else {
|
148
|
-
console.log(data.toString());
|
149
|
-
}
|
150
|
-
});
|
151
|
-
|
152
|
-
p.stderr.on('data', (data) => {
|
153
|
-
console.error(data.toString());
|
154
|
-
});
|
155
|
-
});
|
156
|
-
},
|
157
|
-
});
|