pinokiod 3.8.151 → 3.8.152
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/kernel/bin/index.js +5 -6
- package/kernel/index.js +3 -3
- package/kernel/loader.js +2 -0
- package/kernel/router/index.js +0 -2
- package/kernel/router/peer_port_router.js +0 -2
- package/kernel/shells.js +4 -0
- package/package.json +1 -1
- package/server/index.js +129 -12
- package/server/public/commander.js +40 -0
- package/server/public/style.css +12 -2
- package/server/socket.js +12 -1
- package/server/views/app.ejs +2 -0
- package/server/views/network.ejs +79 -9
- package/server/views/prototypes.ejs +21 -0
- package/server/views/setup_home.ejs +13 -3
- package/server/views/{minterm.ejs → shell.ejs} +92 -48
package/kernel/bin/index.js
CHANGED
|
@@ -369,7 +369,7 @@ class Bin {
|
|
|
369
369
|
let channel = chunks[3]
|
|
370
370
|
let coerced = semver.coerce(version)
|
|
371
371
|
let mamba_requirement = ">=24.11.1"
|
|
372
|
-
console.log({ name, channel, version })
|
|
372
|
+
// console.log({ name, channel, version })
|
|
373
373
|
//if (semver.satisfies(coerced, mamba_requirement) && channel === "conda-forge") {
|
|
374
374
|
if (semver.satisfies(coerced, mamba_requirement)) {
|
|
375
375
|
conda_check.mamba = true
|
|
@@ -439,11 +439,10 @@ class Bin {
|
|
|
439
439
|
|
|
440
440
|
if (this.platform === "darwin") {
|
|
441
441
|
// 3. brew
|
|
442
|
-
console.log("## check brew")
|
|
443
442
|
|
|
444
443
|
let brew_path = path.resolve(this.kernel.homedir, "bin", "homebrew")
|
|
445
444
|
let brew_exists = await this.exists(brew_path)
|
|
446
|
-
console.log({ brew_path, brew_exists })
|
|
445
|
+
// console.log({ brew_path, brew_exists })
|
|
447
446
|
|
|
448
447
|
let brew = []
|
|
449
448
|
if (brew_exists) {
|
|
@@ -451,7 +450,7 @@ class Bin {
|
|
|
451
450
|
res = await this.exec({ message: `brew list -1`, conda: { skip: true } }, (stream) => {
|
|
452
451
|
// console.log("brew list check", { stream })
|
|
453
452
|
})
|
|
454
|
-
console.log("BREW", res.response)
|
|
453
|
+
// console.log("BREW", res.response)
|
|
455
454
|
lines = res.response.split(/[\r\n]+/).slice(0, -1) // ignore last line since it's the prompt
|
|
456
455
|
let end = false
|
|
457
456
|
for(let line of lines) {
|
|
@@ -475,7 +474,7 @@ class Bin {
|
|
|
475
474
|
|
|
476
475
|
|
|
477
476
|
// check brew_installed
|
|
478
|
-
console.log("checking brew installed")
|
|
477
|
+
// console.log("checking brew installed")
|
|
479
478
|
let e = await this.kernel.bin.exists("homebrew")
|
|
480
479
|
let { stdout }= await this.exec({ message: "xcode-select -p", conda: { skip: true } }, (stream) => { })
|
|
481
480
|
let e2 = /(.*Library.*Developer.*CommandLineTools.*|.*Xcode.*Developer.*)/gi.test(stdout)
|
|
@@ -493,7 +492,7 @@ class Bin {
|
|
|
493
492
|
e4 = /xcode-select version ([0-9]+)/gi.exec(result.stdout)
|
|
494
493
|
if (e4 && e4.length > 1) {
|
|
495
494
|
let version = Number(e4[1])
|
|
496
|
-
console.log("xcode-select version", version)
|
|
495
|
+
// console.log("xcode-select version", version)
|
|
497
496
|
if (version >= 2349) {
|
|
498
497
|
e4 = true
|
|
499
498
|
} else {
|
package/kernel/index.js
CHANGED
|
@@ -257,12 +257,12 @@ class Kernel {
|
|
|
257
257
|
}
|
|
258
258
|
// console.log("kernel.refresh", { active, notify_peers })
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
let caddy_installed = await this.bin.check_installed({ name: "caddy" })
|
|
261
261
|
|
|
262
262
|
// 1. https
|
|
263
263
|
// 2. https + local share
|
|
264
264
|
// console.log("caddy installed?", caddy_installed)
|
|
265
|
-
|
|
265
|
+
if (caddy_installed && https_active) {
|
|
266
266
|
|
|
267
267
|
// 1. get the process list
|
|
268
268
|
await this.processes.refresh()
|
|
@@ -293,7 +293,7 @@ class Kernel {
|
|
|
293
293
|
// 9. announce self to the peer network
|
|
294
294
|
this.peer.announce()
|
|
295
295
|
|
|
296
|
-
|
|
296
|
+
}
|
|
297
297
|
|
|
298
298
|
//if (https_installed && peer_active) {
|
|
299
299
|
|
package/kernel/loader.js
CHANGED
|
@@ -43,12 +43,14 @@ class Loader {
|
|
|
43
43
|
async requireJSON(filepath) {
|
|
44
44
|
let config
|
|
45
45
|
try { config = require(filepath) } catch (e) {
|
|
46
|
+
console.log(e)
|
|
46
47
|
}
|
|
47
48
|
return config
|
|
48
49
|
}
|
|
49
50
|
async requireJS(filepath) {
|
|
50
51
|
let config
|
|
51
52
|
try { config = require(filepath) } catch (e) {
|
|
53
|
+
console.log(e)
|
|
52
54
|
}
|
|
53
55
|
try {
|
|
54
56
|
// if the required module is a class, return the instantiated object
|
package/kernel/router/index.js
CHANGED
|
@@ -33,7 +33,6 @@ class Router {
|
|
|
33
33
|
this.custom_routers = {}
|
|
34
34
|
}
|
|
35
35
|
async init() {
|
|
36
|
-
console.log("router.init")
|
|
37
36
|
// if ~/pinokio/network doesn't exist, clone
|
|
38
37
|
let exists = await this.kernel.exists("network/system")
|
|
39
38
|
if (!exists) {
|
|
@@ -190,7 +189,6 @@ class Router {
|
|
|
190
189
|
await this.fill()
|
|
191
190
|
}
|
|
192
191
|
this.mapping = this._mapping
|
|
193
|
-
console.log("after local()", JSON.stringify(this.mapping, null, 2))
|
|
194
192
|
}
|
|
195
193
|
|
|
196
194
|
// set remote config
|
|
@@ -9,9 +9,7 @@ class PeerPortRouter extends Processor {
|
|
|
9
9
|
}
|
|
10
10
|
handle(peer) {
|
|
11
11
|
let https_domains_mapping = this.router.info[peer.host]
|
|
12
|
-
console.log({ https_domains_mapping })
|
|
13
12
|
for(let dial in https_domains_mapping) {
|
|
14
|
-
console.log({ dial })
|
|
15
13
|
let parsed_dial = this.parse_ip(dial)
|
|
16
14
|
if (parsed_dial.host !== peer.host) {
|
|
17
15
|
// ONLY connect for 127.0.0.1 or localhost
|
package/kernel/shells.js
CHANGED
|
@@ -99,6 +99,7 @@ class Shells {
|
|
|
99
99
|
break: false
|
|
100
100
|
}]
|
|
101
101
|
params.on = params.on.concat(defaultHandlers)
|
|
102
|
+
|
|
102
103
|
let response = await sh.start(params, async (stream) => {
|
|
103
104
|
/*
|
|
104
105
|
{
|
|
@@ -462,6 +463,9 @@ class Shells {
|
|
|
462
463
|
return shell.group === group
|
|
463
464
|
})
|
|
464
465
|
return found
|
|
466
|
+
} else if (request.filter) {
|
|
467
|
+
let found = this.shells.filter(request.filter)
|
|
468
|
+
return found
|
|
465
469
|
}
|
|
466
470
|
}
|
|
467
471
|
get(id) {
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -19,7 +19,7 @@ const semver = require('semver')
|
|
|
19
19
|
const fse = require('fs-extra')
|
|
20
20
|
const QRCode = require('qrcode')
|
|
21
21
|
const axios = require('axios')
|
|
22
|
-
|
|
22
|
+
const crypto = require('crypto')
|
|
23
23
|
|
|
24
24
|
const git = require('isomorphic-git')
|
|
25
25
|
const http = require('isomorphic-git/http/node')
|
|
@@ -1126,6 +1126,7 @@ class Server {
|
|
|
1126
1126
|
|
|
1127
1127
|
// check if there is a running process with this folder name
|
|
1128
1128
|
let runningApps = new Set()
|
|
1129
|
+
console.log("API RUNNING", this.kernel.api.running)
|
|
1129
1130
|
for(let key in this.kernel.api.running) {
|
|
1130
1131
|
let p = this.kernel.path("api", items[i].name) + path.sep
|
|
1131
1132
|
//let re = new RegExp(items[i].name)
|
|
@@ -1143,6 +1144,17 @@ class Server {
|
|
|
1143
1144
|
running.push(items[i])
|
|
1144
1145
|
// break
|
|
1145
1146
|
}
|
|
1147
|
+
let shell = this.kernel.shell.find({
|
|
1148
|
+
filter: (shell) => {
|
|
1149
|
+
return shell.id.startsWith(items[i].name + "_")
|
|
1150
|
+
}
|
|
1151
|
+
})
|
|
1152
|
+
if (shell.length > 0) {
|
|
1153
|
+
items[i].running = true
|
|
1154
|
+
items[i].index = index
|
|
1155
|
+
index++;
|
|
1156
|
+
running.push(items[i])
|
|
1157
|
+
}
|
|
1146
1158
|
}
|
|
1147
1159
|
if (!items[i].running) {
|
|
1148
1160
|
items[i].index = index
|
|
@@ -1156,6 +1168,7 @@ class Server {
|
|
|
1156
1168
|
|
|
1157
1169
|
running = this.getItems(running, meta, p)
|
|
1158
1170
|
notRunning = this.getItems(notRunning, meta, p)
|
|
1171
|
+
console.log({ notRunning })
|
|
1159
1172
|
|
|
1160
1173
|
// check running for each
|
|
1161
1174
|
// running_items
|
|
@@ -1423,6 +1436,61 @@ class Server {
|
|
|
1423
1436
|
menuitem.href = menuitem.href + "?" + new URLSearchParams(menuitem.params).toString();
|
|
1424
1437
|
}
|
|
1425
1438
|
|
|
1439
|
+
|
|
1440
|
+
if (menuitem.shell) {
|
|
1441
|
+
/*
|
|
1442
|
+
shell :- {
|
|
1443
|
+
id (optional),
|
|
1444
|
+
path (required), // api, bin, prototype, network, api/
|
|
1445
|
+
message (optional), // if not specified, start an empty shell
|
|
1446
|
+
venv,
|
|
1447
|
+
input, // input mode if true
|
|
1448
|
+
callback, // callback url after shutting down
|
|
1449
|
+
kill, // when to kill (regular expression)
|
|
1450
|
+
}
|
|
1451
|
+
*/
|
|
1452
|
+
|
|
1453
|
+
let rendered = this.kernel.template.render(menuitem.shell, {})
|
|
1454
|
+
let params = new URLSearchParams()
|
|
1455
|
+
// if (rendered.id) {
|
|
1456
|
+
// params.set("id", encodeURIComponent(rendered.id))
|
|
1457
|
+
// } else {
|
|
1458
|
+
// let shell_id = "sh_" + name + "_" + i
|
|
1459
|
+
// params.set("id", encodeURIComponent(shell_id))
|
|
1460
|
+
// }
|
|
1461
|
+
let basePath = this.kernel.path("api", name)
|
|
1462
|
+
if (rendered.path) {
|
|
1463
|
+
params.set("path", encodeURIComponent(this.kernel.api.filePath(rendered.path, basePath)))
|
|
1464
|
+
} else {
|
|
1465
|
+
params.set("path", encodeURIComponent(basePath))
|
|
1466
|
+
}
|
|
1467
|
+
if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
1468
|
+
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
1469
|
+
if (rendered.input) params.set("input", true)
|
|
1470
|
+
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
1471
|
+
if (rendered.env) {
|
|
1472
|
+
for(let key in rendered.env) {
|
|
1473
|
+
let env_key = "env." + key
|
|
1474
|
+
params.set(env_key, rendered.env[key])
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
// deterministic shell id generation
|
|
1479
|
+
// `${api_path}_${i}_${hash}`
|
|
1480
|
+
let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
1481
|
+
let shell_id
|
|
1482
|
+
if (rendered.id) {
|
|
1483
|
+
shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
1484
|
+
} else {
|
|
1485
|
+
shell_id = encodeURIComponent(`${name}_${i}_${hash}`)
|
|
1486
|
+
}
|
|
1487
|
+
menuitem.href = "/shell/" + shell_id + "?" + params.toString()
|
|
1488
|
+
let shell = this.kernel.shell.get(shell_id)
|
|
1489
|
+
if (shell) {
|
|
1490
|
+
menuitem.running = true
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1426
1494
|
if (menuitem.href) {
|
|
1427
1495
|
let u
|
|
1428
1496
|
if (menuitem.href.startsWith("http")) {
|
|
@@ -2222,12 +2290,12 @@ class Server {
|
|
|
2222
2290
|
//let home = this.kernel.store.get("home")
|
|
2223
2291
|
this.app.get("/", ex(async (req, res) => {
|
|
2224
2292
|
// check bin folder
|
|
2225
|
-
let bin_path = this.kernel.path("bin/miniconda")
|
|
2226
|
-
let bin_exists = await this.exists(bin_path)
|
|
2227
|
-
if (!bin_exists) {
|
|
2228
|
-
res.redirect("/setup")
|
|
2229
|
-
return
|
|
2230
|
-
}
|
|
2293
|
+
// let bin_path = this.kernel.path("bin/miniconda")
|
|
2294
|
+
// let bin_exists = await this.exists(bin_path)
|
|
2295
|
+
// if (!bin_exists) {
|
|
2296
|
+
// res.redirect("/setup")
|
|
2297
|
+
// return
|
|
2298
|
+
// }
|
|
2231
2299
|
|
|
2232
2300
|
|
|
2233
2301
|
if (req.query.mode !== "settings" && !home) {
|
|
@@ -2456,14 +2524,60 @@ class Server {
|
|
|
2456
2524
|
})
|
|
2457
2525
|
}
|
|
2458
2526
|
}))
|
|
2459
|
-
this.app.get("/
|
|
2460
|
-
|
|
2527
|
+
this.app.get("/shell/:id", ex(async (req, res) => {
|
|
2528
|
+
/*
|
|
2529
|
+
req.query := {
|
|
2530
|
+
path (required), // api, bin, prototype, network, api/
|
|
2531
|
+
message (optional), // if not specified, start an empty shell
|
|
2532
|
+
venv,
|
|
2533
|
+
callback,
|
|
2534
|
+
kill, // regex for killing
|
|
2535
|
+
env.<key1>,
|
|
2536
|
+
env.<key2>,
|
|
2537
|
+
...
|
|
2538
|
+
}
|
|
2539
|
+
*/
|
|
2540
|
+
|
|
2541
|
+
console.log("SHELLS", this.kernel.shell.shells.map((s) => { return { id: s.id, message: s.params.message } }))
|
|
2542
|
+
// create a new term from cwd
|
|
2543
|
+
let id = decodeURIComponent(req.params.id)
|
|
2544
|
+
let cwd = this.kernel.path(this.kernel.api.filePath(decodeURIComponent(req.query.path)))
|
|
2545
|
+
let message = req.query.message ? decodeURIComponent(req.query.message) : null
|
|
2546
|
+
let venv = req.query.venv ? decodeURIComponent(req.query.venv) : null
|
|
2547
|
+
let input = req.query.input ? true : false
|
|
2548
|
+
let callback = req.query.callback ? decodeURIComponent(req.query.callback) : null
|
|
2549
|
+
let env = {}
|
|
2550
|
+
for(let env_key in req.query) {
|
|
2551
|
+
if (env_key.startsWith("env.")) {
|
|
2552
|
+
let chunks = env_key.split(".")
|
|
2553
|
+
let key = chunks.slice(1).join(".")
|
|
2554
|
+
env[key] = req.query[env_key]
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
let shell = this.kernel.shell.get(id)
|
|
2559
|
+
console.log({ shell })
|
|
2560
|
+
res.render("shell", {
|
|
2461
2561
|
theme: this.theme,
|
|
2462
2562
|
agent: this.agent,
|
|
2463
|
-
|
|
2464
|
-
|
|
2563
|
+
id,
|
|
2564
|
+
cwd,
|
|
2565
|
+
message,
|
|
2566
|
+
venv,
|
|
2567
|
+
env,
|
|
2568
|
+
input,
|
|
2569
|
+
callback,
|
|
2570
|
+
running: (shell ? true : false)
|
|
2465
2571
|
})
|
|
2466
2572
|
}))
|
|
2573
|
+
// this.app.get("/terminal/:api/:id", ex(async (req, res) => {
|
|
2574
|
+
// res.render("shell", {
|
|
2575
|
+
// theme: this.theme,
|
|
2576
|
+
// agent: this.agent,
|
|
2577
|
+
// cwd: this.kernel.path("api/" + req.params.api),
|
|
2578
|
+
// id: req.params.id
|
|
2579
|
+
// })
|
|
2580
|
+
// }))
|
|
2467
2581
|
this.app.get("/peer_check", ex(async (req, res) => {
|
|
2468
2582
|
if (this.kernel.peer.refreshing) {
|
|
2469
2583
|
res.json({ updated: false })
|
|
@@ -2532,7 +2646,7 @@ class Server {
|
|
|
2532
2646
|
})
|
|
2533
2647
|
console.log({ requirements, install_required, requirements_pending })
|
|
2534
2648
|
|
|
2535
|
-
if (install_required) {
|
|
2649
|
+
if (!requirements_pending && install_required) {
|
|
2536
2650
|
res.redirect("/setup/network?callback=/network")
|
|
2537
2651
|
return
|
|
2538
2652
|
}
|
|
@@ -2617,6 +2731,8 @@ class Server {
|
|
|
2617
2731
|
}
|
|
2618
2732
|
}
|
|
2619
2733
|
|
|
2734
|
+
|
|
2735
|
+
|
|
2620
2736
|
res.render("network", {
|
|
2621
2737
|
current_host: this.kernel.peer.host,
|
|
2622
2738
|
peers,
|
|
@@ -3774,6 +3890,7 @@ class Server {
|
|
|
3774
3890
|
this.app.post("/network", ex(async (req, res) => {
|
|
3775
3891
|
if (this.kernel.homedir) {
|
|
3776
3892
|
let fullpath = path.resolve(this.kernel.homedir, "ENVIRONMENT")
|
|
3893
|
+
console.log("req.body", req.body)
|
|
3777
3894
|
await Util.update_env(fullpath, req.body)
|
|
3778
3895
|
res.json({ success: true })
|
|
3779
3896
|
} else {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const Commander = async (config) => {
|
|
2
|
+
console.log({ config })
|
|
3
|
+
let result = await Swal.fire({
|
|
4
|
+
title: `<i class='${config.icon}'></i> ${config.title}`,
|
|
5
|
+
html: `<div class='commander-dialog'>${config.description}</div>
|
|
6
|
+
<input style='width:100%; padding: 10px;' class='cmd' type='text' placeholder='${config.placeholder}'>`,
|
|
7
|
+
allowOutsideClick: true,
|
|
8
|
+
focusConfirm: false,
|
|
9
|
+
// showCancelButton: true,
|
|
10
|
+
confirmButtonText: 'OK',
|
|
11
|
+
didOpen: () => {
|
|
12
|
+
const input = document.querySelector(".cmd")
|
|
13
|
+
input.focus()
|
|
14
|
+
},
|
|
15
|
+
preConfirm: () => {
|
|
16
|
+
let message = config.message(Swal.getPopup().querySelector(".cmd").value)
|
|
17
|
+
let path = config.path
|
|
18
|
+
let callback = config.callback
|
|
19
|
+
let search_params = new URLSearchParams()
|
|
20
|
+
search_params.set("message", message)
|
|
21
|
+
if (config.callback) {
|
|
22
|
+
search_params.set("callback", config.callback)
|
|
23
|
+
}
|
|
24
|
+
search_params.set("path", config.path)
|
|
25
|
+
if (config.venv) {
|
|
26
|
+
search_params.set("venv", config.venv)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// env
|
|
30
|
+
if (config.env) {
|
|
31
|
+
for(let key in config.env) {
|
|
32
|
+
search_params.set("env." + key, config.env[key])
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
let terminal_path = "/shell/" + config.id + "?" + search_params.toString()
|
|
36
|
+
location.href = terminal_path
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
console.log({ result })
|
|
40
|
+
}
|
package/server/public/style.css
CHANGED
|
@@ -571,6 +571,16 @@ body.fullscreen .btn {
|
|
|
571
571
|
border: 1px solid rgba(0,0,0,0.1);
|
|
572
572
|
*/
|
|
573
573
|
}
|
|
574
|
+
body.dark .commander-dialog {
|
|
575
|
+
background: rgba(255,255,100,0.08);
|
|
576
|
+
}
|
|
577
|
+
.commander-dialog {
|
|
578
|
+
font-size: 14px;
|
|
579
|
+
text-align: left;
|
|
580
|
+
margin-bottom: 10px;
|
|
581
|
+
padding: 15px;
|
|
582
|
+
background: rgba(0,0,100,0.04);
|
|
583
|
+
}
|
|
574
584
|
.runnables {
|
|
575
585
|
padding: 20px;
|
|
576
586
|
box-sizing: border-box;
|
|
@@ -1067,7 +1077,7 @@ body.dark .line i {
|
|
|
1067
1077
|
/*
|
|
1068
1078
|
padding: 10px;
|
|
1069
1079
|
*/
|
|
1070
|
-
padding:
|
|
1080
|
+
padding: 8px;
|
|
1071
1081
|
/*
|
|
1072
1082
|
width: 40px;
|
|
1073
1083
|
height: 40px;
|
|
@@ -1681,7 +1691,7 @@ body.dark .not-running-apps, body.dark .running-apps {
|
|
|
1681
1691
|
}
|
|
1682
1692
|
*/
|
|
1683
1693
|
.running-apps .line img {
|
|
1684
|
-
|
|
1694
|
+
border: 3px solid #82bc09;
|
|
1685
1695
|
/*
|
|
1686
1696
|
border: 3px solid #8fd400;
|
|
1687
1697
|
*/
|
package/server/socket.js
CHANGED
|
@@ -19,6 +19,7 @@ class Socket {
|
|
|
19
19
|
});
|
|
20
20
|
ws.on('message', async (message) => {
|
|
21
21
|
const req = JSON.parse(message);
|
|
22
|
+
console.log({ req })
|
|
22
23
|
if (req.response) {
|
|
23
24
|
this.parent.kernel.api.respond(req)
|
|
24
25
|
} else {
|
|
@@ -89,7 +90,17 @@ class Socket {
|
|
|
89
90
|
let buf = this.buffer[req.id]
|
|
90
91
|
let sh = this.active_shell[req.id]
|
|
91
92
|
this.subscribe(ws, req.id, buf, sh)
|
|
92
|
-
if (
|
|
93
|
+
if (sh) {
|
|
94
|
+
// if the active shell exists, check if it's killed
|
|
95
|
+
// if the shell is running, don't do anything
|
|
96
|
+
// if the shell is not running, run the request
|
|
97
|
+
let shell = this.parent.kernel.shell.get(sh)
|
|
98
|
+
console.log("get shell for", sh, shell)
|
|
99
|
+
if (!shell) {
|
|
100
|
+
this.parent.kernel.api.process(req)
|
|
101
|
+
}
|
|
102
|
+
// if it's not killed, don't do anything
|
|
103
|
+
} else {
|
|
93
104
|
this.parent.kernel.api.process(req)
|
|
94
105
|
}
|
|
95
106
|
} else {
|
package/server/views/app.ejs
CHANGED
|
@@ -686,9 +686,11 @@ body.dark .loader-container {
|
|
|
686
686
|
<a target="<%=src%>" href="<%=src%>" class='btn header-item frame-link' data-index="0">
|
|
687
687
|
<div class='tab'><i class="fa-regular fa-folder-open"></i> Files <div class='disk-usage'></div></div>
|
|
688
688
|
</a>
|
|
689
|
+
<!--
|
|
689
690
|
<a target="_blank" href="/terminal/<%=name%>/<%=Date.now()%>" class='btn header-item frame-link' data-index="1">
|
|
690
691
|
<div class='tab'><i class="fa-solid fa-terminal"></i> Terminal</div>
|
|
691
692
|
</a>
|
|
693
|
+
-->
|
|
692
694
|
<a target="_blank" href="<%=profile%>" class='btn header-item frame-link'>
|
|
693
695
|
<div class='tab'><i class="fa-regular fa-circle-user"></i> Publisher</div>
|
|
694
696
|
</a>
|
package/server/views/network.ejs
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<link href="/noty.css" rel="stylesheet"/>
|
|
13
13
|
<link href="/style.css" rel="stylesheet"/>
|
|
14
14
|
<script src="/sweetalert2.js"></script>
|
|
15
|
+
<script src="/commander.js"></script>
|
|
15
16
|
<% if (agent === "electron") { %>
|
|
16
17
|
<link href="/electron.css" rel="stylesheet"/>
|
|
17
18
|
<% } %>
|
|
@@ -200,6 +201,7 @@ a.ln:hover {
|
|
|
200
201
|
box-sizing: border-box;
|
|
201
202
|
}
|
|
202
203
|
.container-row.current {
|
|
204
|
+
background: rgba(0,0,255,0.08);
|
|
203
205
|
}
|
|
204
206
|
/*
|
|
205
207
|
.container-row.current .header-label-sub {
|
|
@@ -212,6 +214,11 @@ a.ln:hover {
|
|
|
212
214
|
*/
|
|
213
215
|
padding: 10px 0;
|
|
214
216
|
}
|
|
217
|
+
#advanced-label {
|
|
218
|
+
text-decoration: underline;
|
|
219
|
+
color: royalblue;
|
|
220
|
+
cursor: pointer;
|
|
221
|
+
}
|
|
215
222
|
.container-row table {
|
|
216
223
|
width: 100%;
|
|
217
224
|
}
|
|
@@ -266,14 +273,16 @@ td:first-child, th:first-child {
|
|
|
266
273
|
.config-row {
|
|
267
274
|
padding: 10px 20px 0 0;
|
|
268
275
|
}
|
|
269
|
-
.
|
|
276
|
+
.label {
|
|
270
277
|
padding-bottom: 5px;
|
|
271
278
|
font-weight: bold;
|
|
272
279
|
}
|
|
273
280
|
.config-row input[type=text] {
|
|
274
281
|
padding: 7px;
|
|
275
282
|
}
|
|
276
|
-
|
|
283
|
+
.btn.save {
|
|
284
|
+
padding: 8px;
|
|
285
|
+
}
|
|
277
286
|
.switcher {
|
|
278
287
|
position: relative;
|
|
279
288
|
display: inline-block;
|
|
@@ -340,6 +349,22 @@ input:checked + .slider:before {
|
|
|
340
349
|
text-align: center;
|
|
341
350
|
padding: 50px;
|
|
342
351
|
}
|
|
352
|
+
.advanced a.btn {
|
|
353
|
+
text-align: center;
|
|
354
|
+
}
|
|
355
|
+
.advanced {
|
|
356
|
+
margin: 20px 0;
|
|
357
|
+
}
|
|
358
|
+
.advanced h3 {
|
|
359
|
+
margin: 0 0 5px;
|
|
360
|
+
}
|
|
361
|
+
.advanced .row {
|
|
362
|
+
display: flex;
|
|
363
|
+
}
|
|
364
|
+
.advanced input[type=text] {
|
|
365
|
+
flex-grow: 1;
|
|
366
|
+
padding: 10px;
|
|
367
|
+
}
|
|
343
368
|
|
|
344
369
|
|
|
345
370
|
@media only screen and (max-width: 480px) {
|
|
@@ -377,8 +402,9 @@ input:checked + .slider:before {
|
|
|
377
402
|
<div class='config'>
|
|
378
403
|
<div class='config-header'>
|
|
379
404
|
<div class='header-label'><i class='fa-solid fa-wifi'></i> Network</div>
|
|
380
|
-
<div class='desc'>
|
|
405
|
+
<div class='desc'>Instant HTTPS for every app on your local network.</div>
|
|
381
406
|
</div>
|
|
407
|
+
<!--
|
|
382
408
|
<div class='config-body'>
|
|
383
409
|
<div class='config-row'>
|
|
384
410
|
<div class='label'>Instant HTTPS</div>
|
|
@@ -388,21 +414,41 @@ input:checked + .slider:before {
|
|
|
388
414
|
</label>
|
|
389
415
|
</div>
|
|
390
416
|
</div>
|
|
417
|
+
-->
|
|
391
418
|
<div class='config-body'>
|
|
419
|
+
<!--
|
|
392
420
|
<div class='config-row'>
|
|
393
|
-
<div class='label'>Network Share</div>
|
|
421
|
+
<div class='label'>Local Network Share</div>
|
|
394
422
|
<label class="switcher">
|
|
395
423
|
<input id='peer_active' type="checkbox" <%=peer_active ? 'checked' : ''%>>
|
|
396
424
|
<span class="slider"></span>
|
|
397
425
|
</label>
|
|
398
426
|
</div>
|
|
427
|
+
-->
|
|
428
|
+
<div class='config-row'>
|
|
429
|
+
<div id='active-label' class='label'><%=peer_active ? "On" : "Off"%></div>
|
|
430
|
+
<label class="switcher">
|
|
431
|
+
<input id='active' type="checkbox" <%=peer_active ? 'checked' : ''%>>
|
|
432
|
+
<span class="slider"></span>
|
|
433
|
+
</label>
|
|
434
|
+
</div>
|
|
399
435
|
<div class='config-row' id='network_name'>
|
|
400
436
|
<div class='label'>Network Name</div>
|
|
401
437
|
<input id='name' type='text' value="<%=name%>">
|
|
402
438
|
</div>
|
|
403
|
-
<div class='flexible'></div>
|
|
404
439
|
<button class='btn save'>Save</button>
|
|
405
440
|
</div>
|
|
441
|
+
<div class='advanced'>
|
|
442
|
+
<div class='row'>
|
|
443
|
+
<div id='advanced-label' class='label'>Advanced</div>
|
|
444
|
+
</div>
|
|
445
|
+
<!--
|
|
446
|
+
<div id='advanced-input' class='row hidden'>
|
|
447
|
+
<input id='git' type='text' placeholder='git url for custom network router'>
|
|
448
|
+
<a id="custom_download" class='btn'>Install</a>
|
|
449
|
+
</div>
|
|
450
|
+
-->
|
|
451
|
+
</div>
|
|
406
452
|
</div>
|
|
407
453
|
<div class='loading hidden'>
|
|
408
454
|
<i class="fa-solid fa-circle-notch fa-spin"></i> Stand by. Do not close this window..
|
|
@@ -549,19 +595,36 @@ input:checked + .slider:before {
|
|
|
549
595
|
</div>
|
|
550
596
|
</main>
|
|
551
597
|
<script>
|
|
552
|
-
|
|
598
|
+
document.querySelector("#advanced-label").addEventListener("click", (e) => {
|
|
599
|
+
//document.querySelector("#advanced-input").classList.toggle("hidden")
|
|
600
|
+
Commander({
|
|
601
|
+
callback: "/network",
|
|
602
|
+
path: "~/network",
|
|
603
|
+
icon: "fa-solid fa-circle-down",
|
|
604
|
+
title: "Custom Router",
|
|
605
|
+
placeholder: "enter a custom router git url",
|
|
606
|
+
description: `<div>you can write your own custom routers to handle custom request handling for any port <a target="_blank" href="https://program.pinokio.computer">Learn more</a></div>`,
|
|
607
|
+
message: (url) => {
|
|
608
|
+
let name = new URL(url).pathname.split("/").slice(-2).join("_")
|
|
609
|
+
return encodeURIComponent(`git clone ${url} ${name}`)
|
|
610
|
+
}
|
|
611
|
+
})
|
|
612
|
+
})
|
|
613
|
+
if (document.querySelector("#active").checked) {
|
|
553
614
|
console.log("checked")
|
|
554
615
|
document.querySelector("#network_name").classList.remove("hidden")
|
|
555
616
|
} else {
|
|
556
617
|
console.log("not checked")
|
|
557
618
|
document.querySelector("#network_name").classList.add("hidden")
|
|
558
619
|
}
|
|
559
|
-
document.querySelector("#
|
|
620
|
+
document.querySelector("#active").addEventListener("change", (e)=> {
|
|
560
621
|
console.log(e.target.checked)
|
|
561
622
|
if (e.target.checked) {
|
|
562
623
|
document.querySelector("#network_name").classList.remove("hidden")
|
|
624
|
+
document.querySelector("#active-label").innerHTML = "On"
|
|
563
625
|
} else {
|
|
564
626
|
document.querySelector("#network_name").classList.add("hidden")
|
|
627
|
+
document.querySelector("#active-label").innerHTML = "Off"
|
|
565
628
|
}
|
|
566
629
|
})
|
|
567
630
|
document.querySelector("main").addEventListener("click", async (e) => {
|
|
@@ -574,13 +637,20 @@ document.querySelector("main").addEventListener("click", async (e) => {
|
|
|
574
637
|
}
|
|
575
638
|
|
|
576
639
|
if (target) {
|
|
640
|
+
let active = document.querySelector("#active").checked ? "1": "0"
|
|
641
|
+
let body = {
|
|
642
|
+
PINOKIO_NETWORK_NAME: document.querySelector("#name").value,
|
|
643
|
+
PINOKIO_NETWORK_ACTIVE: active,
|
|
644
|
+
PINOKIO_HTTPS_ACTIVE: active,
|
|
645
|
+
}
|
|
646
|
+
/*
|
|
577
647
|
let body = {
|
|
578
|
-
PINOKIO_NETWORK_NAME: document.querySelector("#
|
|
648
|
+
PINOKIO_NETWORK_NAME: document.querySelector("#name").value,
|
|
579
649
|
PINOKIO_NETWORK_ACTIVE: (document.querySelector("#peer_active").checked ? "1": "0"),
|
|
580
650
|
PINOKIO_HTTPS_ACTIVE: (document.querySelector("#https_active").checked ? "1": "0")
|
|
581
651
|
}
|
|
652
|
+
*/
|
|
582
653
|
console.log(body)
|
|
583
|
-
debugger
|
|
584
654
|
let r = await fetch("/network", {
|
|
585
655
|
method: "post",
|
|
586
656
|
headers: { "Content-Type": "application/json" },
|
|
@@ -141,6 +141,9 @@ body.dark .badge {
|
|
|
141
141
|
height: 20px;
|
|
142
142
|
margin-right: 10px;
|
|
143
143
|
}
|
|
144
|
+
.prototype-header {
|
|
145
|
+
padding: 10px;
|
|
146
|
+
}
|
|
144
147
|
/*
|
|
145
148
|
body.dark .browser-options-row {
|
|
146
149
|
border-top: 1px solid rgba(255,255,255,0.05);
|
|
@@ -183,6 +186,7 @@ body.dark .browser-options-row {
|
|
|
183
186
|
<script src="/filepond-plugin-image-transform.min.js"></script>
|
|
184
187
|
<script src="/filepond.min.js"></script>
|
|
185
188
|
<script src="/fscreator.js"></script>
|
|
189
|
+
<script src="/commander.js"></script>
|
|
186
190
|
</head>
|
|
187
191
|
<body class='<%=theme%>'>
|
|
188
192
|
<header class='navheader grabbable'>
|
|
@@ -213,6 +217,9 @@ body.dark .browser-options-row {
|
|
|
213
217
|
<main>
|
|
214
218
|
<div id='terminal' class='hidden'></div>
|
|
215
219
|
<div class='container'>
|
|
220
|
+
<div class='prototype-header'>
|
|
221
|
+
<a class='btn' id='download'><i class='fa-solid fa-download'></i> Download a prototype</a>
|
|
222
|
+
</div>
|
|
216
223
|
<div class='folder-templates drawer'>
|
|
217
224
|
<% items.forEach((folder, i) => { %>
|
|
218
225
|
<a href="/prototypes/<%=folder.id%>" class='line folder' data-id="<%=folder.id%>" data-icon="<%=folder.icon%>" data-name="<%=folder.title%>" data-description="<%=folder.description || ''%>" data-title="<%=folder.title%>" data-index="<%=i%>">
|
|
@@ -312,6 +319,20 @@ const renderSearch = () => {
|
|
|
312
319
|
|
|
313
320
|
renderSearch()
|
|
314
321
|
|
|
322
|
+
document.querySelector("#download").addEventListener("click", (e) => {
|
|
323
|
+
Commander({
|
|
324
|
+
callback: "/new",
|
|
325
|
+
path: "~/prototype",
|
|
326
|
+
icon: "fa-solid fa-circle-down",
|
|
327
|
+
title: "Download a Prototype",
|
|
328
|
+
placeholder: "enter a custom prototype git url",
|
|
329
|
+
description: `<div>prototypes are recipes for automatically bootstrapping projects. You can write your own custom prototypes <a target="_blank" href="https://program.pinokio.computer">Learn more</a></div>`,
|
|
330
|
+
message: (url) => {
|
|
331
|
+
let name = new URL(url).pathname.split("/").slice(-2).join("_")
|
|
332
|
+
return encodeURIComponent(`git clone ${url} ${name}`)
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
})
|
|
315
336
|
document.querySelector("form input[type=search]").addEventListener("input", (e) => {
|
|
316
337
|
selectedIndex = 0
|
|
317
338
|
selectedBtnIndex = 0
|
|
@@ -153,11 +153,21 @@ body.dark .card {
|
|
|
153
153
|
<a class='path' href="/"><%-logo%></a>
|
|
154
154
|
<div class='flexible'></div>
|
|
155
155
|
<div class='nav-btns'>
|
|
156
|
-
<
|
|
157
|
-
<a class='btn2' href=
|
|
158
|
-
|
|
156
|
+
<a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Network</div></a>
|
|
157
|
+
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
158
|
+
<% if (agent === "electron") { %>
|
|
159
|
+
<a class='btn2' data-filepath="<%=filepath%>"><div><i class="fa-regular fa-folder-open"></i></div><div>Files</div></a>
|
|
160
|
+
<% } %>
|
|
161
|
+
<button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Debug</div></button>
|
|
162
|
+
<a id='downloadlogs' download class='hidden btn2' href="/pinokio/logs.zip"><div><i class="fa-solid fa-download"></i></div><div>Download logs</div></a>
|
|
159
163
|
<a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
|
|
164
|
+
<% if (agent === "electron") { %>
|
|
165
|
+
<a href="/" target="_blank" class='btn2' features="browser"><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
|
|
166
|
+
<% } else { %>
|
|
167
|
+
<a href="/" target="_blank" class='btn2'><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
|
|
168
|
+
<% } %>
|
|
160
169
|
<button id='new-window' title='open a new window' class='btn2'><i class="fa-solid fa-plus"></i></button>
|
|
170
|
+
|
|
161
171
|
</div>
|
|
162
172
|
</h1>
|
|
163
173
|
</h1>
|
|
@@ -157,6 +157,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
157
157
|
text: `[Success] All steps complete`,
|
|
158
158
|
})
|
|
159
159
|
*/
|
|
160
|
+
document.querySelector(".play-btn").classList.remove("hidden")
|
|
161
|
+
document.querySelector(".stop-btn").classList.add("hidden")
|
|
162
|
+
document.querySelector(".starting-btn").classList.add("hidden")
|
|
160
163
|
}
|
|
161
164
|
stop() {
|
|
162
165
|
this.socket.run({
|
|
@@ -197,21 +200,42 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
197
200
|
let query = Object.fromEntries(new URLSearchParams(location.search))
|
|
198
201
|
console.log(">>>>>>>> 1")
|
|
199
202
|
|
|
203
|
+
let firstPacketReceived = false
|
|
200
204
|
this.socket.run({
|
|
201
|
-
method: "kernel.bin.shell_start",
|
|
202
|
-
|
|
205
|
+
//method: "kernel.bin.shell_start",
|
|
206
|
+
method: "kernel.bin.exec",
|
|
207
|
+
<% if (message) { %>
|
|
208
|
+
message: "<%=message%>",
|
|
209
|
+
<% } %>
|
|
210
|
+
<% if (venv) { %>
|
|
211
|
+
venv: "<%=venv%>",
|
|
212
|
+
<% } %>
|
|
213
|
+
<% if (input) { %>
|
|
214
|
+
input: true,
|
|
215
|
+
<% } %>
|
|
216
|
+
<% if (env) { %>
|
|
217
|
+
env: <%-JSON.stringify(env)%>,
|
|
218
|
+
<% } %>
|
|
203
219
|
id: "<%=id%>",
|
|
204
|
-
|
|
205
|
-
path: "<%=cwd%>",
|
|
206
|
-
// },
|
|
220
|
+
path: "<%=cwd%>",
|
|
207
221
|
client: {
|
|
208
222
|
cols: this.term.cols,
|
|
209
223
|
rows: this.term.rows,
|
|
210
224
|
}
|
|
211
225
|
}, async (packet) => {
|
|
212
|
-
|
|
226
|
+
if (!firstPacketReceived) {
|
|
227
|
+
refreshParent({
|
|
228
|
+
type: "start"
|
|
229
|
+
})
|
|
230
|
+
firstPacketReceived = true
|
|
231
|
+
}
|
|
232
|
+
console.log({ packet, type: packet.type })
|
|
213
233
|
if (packet.type === 'start') {
|
|
234
|
+
console.log("refreshParent", packet)
|
|
214
235
|
refreshParent(packet)
|
|
236
|
+
document.querySelector(".play-btn").classList.add("hidden")
|
|
237
|
+
document.querySelector(".starting-btn").classList.add("hidden")
|
|
238
|
+
document.querySelector(".stop-btn").classList.remove("hidden")
|
|
215
239
|
if (packet.data && packet.data.description) {
|
|
216
240
|
if ('current' in packet.data) {
|
|
217
241
|
document.querySelector("footer").innerHTML = `<b>
|
|
@@ -255,12 +279,20 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
255
279
|
this.write(JSON.stringify(packet.data.json2, null, 2).replace(/\n/g, "\r\n"))
|
|
256
280
|
this.write("\r\n")
|
|
257
281
|
}
|
|
282
|
+
document.querySelector(".play-btn").classList.add("hidden")
|
|
283
|
+
document.querySelector(".starting-btn").classList.add("hidden")
|
|
284
|
+
document.querySelector(".stop-btn").classList.remove("hidden")
|
|
258
285
|
} else if (packet.type === 'disconnect') {
|
|
286
|
+
console.log("refreshParent", packet)
|
|
259
287
|
refreshParent(packet)
|
|
260
288
|
this.term.write("\r\nDisconnected...\r\n")
|
|
261
289
|
document.querySelector("footer").innerHTML = "<b>Ready</b>"
|
|
262
290
|
this.socket.close()
|
|
291
|
+
document.querySelector(".play-btn").classList.remove("hidden")
|
|
292
|
+
document.querySelector(".stop-btn").classList.add("hidden")
|
|
263
293
|
} else if (packet.type === 'connect') {
|
|
294
|
+
console.log("refreshParent", packet)
|
|
295
|
+
refreshParent(packet)
|
|
264
296
|
if (packet.data) {
|
|
265
297
|
if (packet.data.shell) {
|
|
266
298
|
shell_id = packet.data.shell
|
|
@@ -269,39 +301,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
269
301
|
this.write(packet.data.state)
|
|
270
302
|
}
|
|
271
303
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
setTimeout(()=> {
|
|
276
|
-
this.term.write(message[i])
|
|
277
|
-
r()
|
|
278
|
-
}, 20)
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
*/
|
|
282
|
-
console.log(">>>>>>>> 2")
|
|
283
|
-
// } else if (packet.type === "key.set") {
|
|
284
|
-
// let keys = await fetch("/pinokio/keys").then((res) => {
|
|
285
|
-
// return res.json()
|
|
286
|
-
// })
|
|
287
|
-
// let input = await ModalInput({
|
|
288
|
-
// title: "Key",
|
|
289
|
-
// description: "select a key",
|
|
290
|
-
// form: [{
|
|
291
|
-
// key: "key",
|
|
292
|
-
// type: "select",
|
|
293
|
-
// items: keys,
|
|
294
|
-
// }, {
|
|
295
|
-
// key: "password",
|
|
296
|
-
// type: "password",
|
|
297
|
-
// }]
|
|
298
|
-
// })
|
|
299
|
-
// if (input) {
|
|
300
|
-
// this.socket.respond({
|
|
301
|
-
// response: input,
|
|
302
|
-
// uri: "~" + location.pathname,
|
|
303
|
-
// })
|
|
304
|
-
// }
|
|
304
|
+
document.querySelector(".play-btn").classList.add("hidden")
|
|
305
|
+
document.querySelector(".starting-btn").classList.add("hidden")
|
|
306
|
+
document.querySelector(".stop-btn").classList.remove("hidden")
|
|
305
307
|
} else if (packet.type === 'wait.end') {
|
|
306
308
|
try {
|
|
307
309
|
Swal.close()
|
|
@@ -435,7 +437,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
435
437
|
n.Noty(payload)
|
|
436
438
|
}
|
|
437
439
|
} else if (packet.type === "result") {
|
|
438
|
-
|
|
440
|
+
this.socket.close()
|
|
439
441
|
} else if (packet.type === "info") {
|
|
440
442
|
n.Noty({
|
|
441
443
|
text: `${packet.data}`,
|
|
@@ -457,6 +459,10 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
457
459
|
// document.querySelector("footer").classList.add("expanded")
|
|
458
460
|
document.querySelector("footer i").className = "fa-solid fa-triangle-exclamation"
|
|
459
461
|
|
|
462
|
+
document.querySelector(".play-btn").classList.remove("hidden")
|
|
463
|
+
document.querySelector(".starting-btn").classList.add("hidden")
|
|
464
|
+
document.querySelector(".stop-btn").classList.add("hidden")
|
|
465
|
+
|
|
460
466
|
document.querySelector("#error-screen").classList.remove("hidden")
|
|
461
467
|
document.querySelector("#error-screen pre").textContent = packet.data
|
|
462
468
|
let instance = new Mark(document.querySelector("#error-screen pre"), {
|
|
@@ -477,6 +483,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
477
483
|
|
|
478
484
|
} else if (packet.type === "event") {
|
|
479
485
|
if (packet.data === "stop") {
|
|
486
|
+
document.querySelector(".stop-btn").classList.add("hidden")
|
|
487
|
+
document.querySelector(".stopped-btn").classList.remove("hidden")
|
|
480
488
|
document.querySelector("footer").innerHTML = "<b>Ready</b>"
|
|
481
489
|
setTimeout(() => {
|
|
482
490
|
|
|
@@ -513,6 +521,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
513
521
|
type: 'success'
|
|
514
522
|
})
|
|
515
523
|
*/
|
|
524
|
+
document.querySelector(".play-btn").classList.remove("hidden")
|
|
525
|
+
document.querySelector(".starting-btn").classList.add("hidden")
|
|
526
|
+
document.querySelector(".stop-btn").classList.add("hidden")
|
|
516
527
|
}, 0)
|
|
517
528
|
//this.socket.close()
|
|
518
529
|
}
|
|
@@ -534,6 +545,15 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
534
545
|
// this.fit.fit()
|
|
535
546
|
// let pageBottom = document.querySelector("#end")
|
|
536
547
|
// pageBottom.scrollIntoView()
|
|
548
|
+
}).then(() => {
|
|
549
|
+
refreshParent({
|
|
550
|
+
type: "disconnect"
|
|
551
|
+
})
|
|
552
|
+
document.querySelector(".stop-btn").classList.add("hidden")
|
|
553
|
+
document.querySelector(".stopped-btn").classList.remove("hidden")
|
|
554
|
+
<% if (callback) { %>
|
|
555
|
+
location.href = "<%=callback%>"
|
|
556
|
+
<% } %>
|
|
537
557
|
})
|
|
538
558
|
})
|
|
539
559
|
}
|
|
@@ -649,7 +669,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
649
669
|
}
|
|
650
670
|
}
|
|
651
671
|
const rpc = new RPC()
|
|
652
|
-
document.querySelector(".stop").addEventListener("click", async (e) => {
|
|
672
|
+
document.querySelector(".stop-btn").addEventListener("click", async (e) => {
|
|
653
673
|
await rpc.stop()
|
|
654
674
|
// socket.run({
|
|
655
675
|
// id: location.pathname,
|
|
@@ -657,13 +677,31 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
657
677
|
// }, (stream) => {
|
|
658
678
|
// console.log("#", stream)
|
|
659
679
|
// })
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
document.querySelector(".
|
|
663
|
-
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
document.querySelector(".play-btn").classList.remove("hidden")
|
|
683
|
+
document.querySelector(".starting-btn").classList.add("hidden")
|
|
664
684
|
document.querySelector(".stop-btn").classList.add("hidden")
|
|
665
685
|
document.querySelector(".stopped-btn").classList.remove("hidden")
|
|
666
686
|
})
|
|
687
|
+
document.querySelector(".play-btn").addEventListener("click", async (e) => {
|
|
688
|
+
document.querySelector(".play-btn").classList.add("hidden")
|
|
689
|
+
document.querySelector(".starting-btn").classList.remove("hidden")
|
|
690
|
+
await rpc.run()
|
|
691
|
+
})
|
|
692
|
+
<% if (running) { %>
|
|
693
|
+
// if running, connect
|
|
694
|
+
rpc.run("listen")
|
|
695
|
+
// hide play button
|
|
696
|
+
document.querySelector(".play-btn").classList.add("hidden")
|
|
697
|
+
// show stop button
|
|
698
|
+
document.querySelector(".stop-btn").classList.remove("hidden")
|
|
699
|
+
<% } else { %>
|
|
700
|
+
// if not running, start
|
|
701
|
+
rpc.run()
|
|
702
|
+
// show starting button
|
|
703
|
+
document.querySelector(".starting-btn").classList.remove("hidden")
|
|
704
|
+
<% } %>
|
|
667
705
|
|
|
668
706
|
window.addEventListener('message', function(event) {
|
|
669
707
|
console.log("Message received from the parent: ", event.data); // Message received from parent
|
|
@@ -681,7 +719,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
681
719
|
}
|
|
682
720
|
}
|
|
683
721
|
});
|
|
684
|
-
rpc.run()
|
|
722
|
+
// rpc.run()
|
|
685
723
|
})
|
|
686
724
|
|
|
687
725
|
</script>
|
|
@@ -689,10 +727,16 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
689
727
|
<body class='<%=theme%>'>
|
|
690
728
|
<header class='navheader grabbable'>
|
|
691
729
|
<div class='navheader3'>
|
|
692
|
-
<div class='btn run
|
|
730
|
+
<div class='hidden btn run play-btn'>
|
|
731
|
+
<span class='play'><i class="fa-solid fa-play"></i> Start</span>
|
|
732
|
+
</div>
|
|
733
|
+
<div class='hidden btn run starting-btn'>
|
|
734
|
+
<span class='starting'><i class="fa-solid fa-circle-notch fa-spin"></i> Starting...</span>
|
|
735
|
+
</div>
|
|
736
|
+
<div class='hidden btn run stop-btn'>
|
|
693
737
|
<span class='stop'><i class="fa-solid fa-stop"></i> Stop</span>
|
|
694
738
|
</div>
|
|
695
|
-
<div class='btn stopped-btn
|
|
739
|
+
<div class='hidden btn stopped-btn'>
|
|
696
740
|
<span class='stopped'><i class="fa-solid fa-hand"></i> Stopped</span>
|
|
697
741
|
</div>
|
|
698
742
|
</div>
|