@makano/rew 1.2.1 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
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
- }
@@ -1,3 +0,0 @@
1
- body {
2
- background-color: #1c2541;
3
- }
@@ -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>
@@ -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
- };
@@ -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
- });