pinokiod 2.15.10 → 2.15.12
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/api/fs/index.js +13 -3
- package/kernel/api/index.js +32 -12
- package/kernel/api/local/index.js +2 -0
- package/kernel/bin/huggingface.js +25 -0
- package/kernel/bin/playwright.js +76 -0
- package/kernel/index.js +28 -2
- package/kernel/lproxy.js +29 -4
- package/package.json +1 -1
- package/server/index.js +75 -7
- package/server/public/lmstudio.jpg +0 -0
- package/server/public/style.css +12 -1
- package/server/views/browser-experimental.ejs +1 -1
- package/server/views/disposable.ejs +313 -0
- package/server/views/editor.ejs +8 -1
- package/server/views/explore.ejs +1 -1
- package/server/views/fullscreen_editor.ejs +8 -1
- package/server/views/index.ejs +8 -2
- package/server/views/proxy.ejs +84 -42
- package/server/views/settings.ejs +1 -1
package/kernel/api/fs/index.js
CHANGED
|
@@ -67,6 +67,7 @@ class FS {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
async link(req, ondata, kernel) {
|
|
70
|
+
console.log("FS.link", req)
|
|
70
71
|
let response = await this.share(req, ondata, kernel)
|
|
71
72
|
return response
|
|
72
73
|
}
|
|
@@ -275,14 +276,22 @@ class FS {
|
|
|
275
276
|
parent: site_packages_root,
|
|
276
277
|
}
|
|
277
278
|
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
if (req.params.options) {
|
|
282
|
+
d.options = req.params.options
|
|
283
|
+
} else {
|
|
284
|
+
d.options = {
|
|
285
|
+
overwrite: true
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
278
289
|
// if the version is NOT final, overwrite.
|
|
279
290
|
let re = /^\d+(\.\d+)*$/ // regex for testing final versions like 1.2, 1.1.1, 1.2.1.1, etc.
|
|
280
291
|
if (re.test(version)) {
|
|
281
292
|
// final version
|
|
282
293
|
} else {
|
|
283
|
-
d.options =
|
|
284
|
-
overwrite: true
|
|
285
|
-
}
|
|
294
|
+
d.options.overwrite = true
|
|
286
295
|
}
|
|
287
296
|
|
|
288
297
|
for(let relpath of copy) {
|
|
@@ -302,6 +311,7 @@ class FS {
|
|
|
302
311
|
ondata({
|
|
303
312
|
raw: "\r\nLINKING DRIVES:\r\n" + JSON.stringify(d, null, 2).replace(/\n/g, "\r\n")
|
|
304
313
|
})
|
|
314
|
+
console.log("CREATE", JSON.stringify(d, null, 2))
|
|
305
315
|
await drive.create(d)
|
|
306
316
|
ondata({
|
|
307
317
|
raw: "Done.\r\n"
|
package/kernel/api/index.js
CHANGED
|
@@ -25,6 +25,21 @@ class Api {
|
|
|
25
25
|
this.proxies = {}
|
|
26
26
|
this.lproxy = new Lproxy()
|
|
27
27
|
}
|
|
28
|
+
get_proxy_url(root, port) {
|
|
29
|
+
if (this.proxies) {
|
|
30
|
+
let proxies = this.proxies[root]
|
|
31
|
+
if (proxies) {
|
|
32
|
+
let filtered = proxies.filter((p) => {
|
|
33
|
+
let re = new RegExp(":"+port+"$")
|
|
34
|
+
return re.test(p.target)
|
|
35
|
+
})
|
|
36
|
+
if (filtered.length > 0) {
|
|
37
|
+
return filtered[0].proxy
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return `http://localhost:${port}`
|
|
42
|
+
}
|
|
28
43
|
checkProxy(config) {
|
|
29
44
|
// if config.name exists, throw error
|
|
30
45
|
// if config.uri exists, throw error
|
|
@@ -41,12 +56,14 @@ class Api {
|
|
|
41
56
|
this.checkProxy({ uri, name })
|
|
42
57
|
// if the name exists, throw error
|
|
43
58
|
// if the uri exists, throw error
|
|
59
|
+
console.log("lproxy start", uri, options)
|
|
44
60
|
let proxy_uri = await this.lproxy.start(uri, options)
|
|
45
61
|
if (this.proxies[scriptPath]) {
|
|
46
62
|
this.proxies[scriptPath].push({ target: uri, proxy: proxy_uri, name})
|
|
47
63
|
} else {
|
|
48
64
|
this.proxies[scriptPath] = [{ target: uri, proxy: proxy_uri, name }]
|
|
49
65
|
}
|
|
66
|
+
console.log("this.proxies", JSON.stringify(this.proxies, null, 2))
|
|
50
67
|
return {
|
|
51
68
|
target: uri,
|
|
52
69
|
proxy: proxy_uri
|
|
@@ -75,6 +92,7 @@ class Api {
|
|
|
75
92
|
})
|
|
76
93
|
}
|
|
77
94
|
}
|
|
95
|
+
console.log("this.proxies", JSON.stringify(this.proxies, null, 2))
|
|
78
96
|
}
|
|
79
97
|
async init() {
|
|
80
98
|
if (this.kernel.homedir) {
|
|
@@ -501,6 +519,7 @@ class Api {
|
|
|
501
519
|
mods.push(r)
|
|
502
520
|
}
|
|
503
521
|
let mod = _.zipObjectDeep(paths, mods)
|
|
522
|
+
console.log("MOD", mod)
|
|
504
523
|
return mod
|
|
505
524
|
|
|
506
525
|
}
|
|
@@ -1184,18 +1203,19 @@ class Api {
|
|
|
1184
1203
|
return path.resolve(cwd, x)
|
|
1185
1204
|
})
|
|
1186
1205
|
|
|
1187
|
-
let merge = await this.construct(cwd, includeFiles, { exclude: [filename], is_sub: false })
|
|
1188
|
-
|
|
1189
|
-
// merge them into the original module
|
|
1190
|
-
|
|
1191
|
-
//exclude "run" attributes
|
|
1192
|
-
|
|
1193
|
-
if (script.run) {
|
|
1194
|
-
if (merge.run) {
|
|
1195
|
-
delete merge.run
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
script = Object.assign(script, merge)
|
|
1206
|
+
// let merge = await this.construct(cwd, includeFiles, { exclude: [filename], is_sub: false })
|
|
1207
|
+
//
|
|
1208
|
+
// // merge them into the original module
|
|
1209
|
+
//
|
|
1210
|
+
// //exclude "run" attributes
|
|
1211
|
+
//
|
|
1212
|
+
// if (script.run) {
|
|
1213
|
+
// if (merge.run) {
|
|
1214
|
+
// delete merge.run
|
|
1215
|
+
// }
|
|
1216
|
+
// }
|
|
1217
|
+
// script = Object.assign(script, merge)
|
|
1218
|
+
console.log("SCRIPT", script)
|
|
1199
1219
|
|
|
1200
1220
|
return { cwd, script }
|
|
1201
1221
|
}
|
|
@@ -25,6 +25,7 @@ class Local {
|
|
|
25
25
|
return res
|
|
26
26
|
}
|
|
27
27
|
async set(req, ondata, kernel) {
|
|
28
|
+
console.log("SET", req)
|
|
28
29
|
/*
|
|
29
30
|
req := {
|
|
30
31
|
"method": "local.set",
|
|
@@ -95,6 +96,7 @@ class Local {
|
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
const p = new Proxy()
|
|
99
|
+
console.log("> proxy", req)
|
|
98
100
|
await p.start(req, ondata, kernel)
|
|
99
101
|
}
|
|
100
102
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class Huggingface {
|
|
2
|
+
async install(req, ondata) {
|
|
3
|
+
await this.kernel.bin.exec({
|
|
4
|
+
message: "conda install -y -c conda-forge huggingface_hub"
|
|
5
|
+
}, ondata)
|
|
6
|
+
}
|
|
7
|
+
async installed() {
|
|
8
|
+
return this.kernel.bin.installed.conda.has("huggingface_hub")
|
|
9
|
+
}
|
|
10
|
+
// env() {
|
|
11
|
+
// return {
|
|
12
|
+
// GIT_CONFIG_GLOBAL: gitconfig_path
|
|
13
|
+
//export CUDA_HOME=/usr/local/cuda
|
|
14
|
+
//export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64
|
|
15
|
+
//export PATH=$PATH:$CUDA_HOME/bin
|
|
16
|
+
//
|
|
17
|
+
// }
|
|
18
|
+
// }
|
|
19
|
+
async uninstall(req, ondata) {
|
|
20
|
+
await this.kernel.bin.exec({
|
|
21
|
+
message: "conda remove huggingface_hub",
|
|
22
|
+
}, ondata)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
module.exports = Huggingface
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const { rimraf } = require('rimraf')
|
|
3
|
+
class Playwright {
|
|
4
|
+
async install(req, ondata) {
|
|
5
|
+
await this.kernel.exec({
|
|
6
|
+
message: [
|
|
7
|
+
// "npm init -y",
|
|
8
|
+
`npm config set prefix ${this.kernel.bin.path("miniconda")}`,
|
|
9
|
+
],
|
|
10
|
+
path: this.kernel.bin.path("playwright"),
|
|
11
|
+
env: {
|
|
12
|
+
PLAYWRIGHT_BROWSERS_PATH: this.kernel.bin.path("playwright/browsers")
|
|
13
|
+
}
|
|
14
|
+
}, ondata)
|
|
15
|
+
await this.kernel.exec({
|
|
16
|
+
message: [
|
|
17
|
+
// "npm init -y",
|
|
18
|
+
"npm install -g playwright@1.49.0",
|
|
19
|
+
// "playwright install chromium",
|
|
20
|
+
],
|
|
21
|
+
//path: this.kernel.bin.path("playwright"),
|
|
22
|
+
env: {
|
|
23
|
+
PLAYWRIGHT_BROWSERS_PATH: this.kernel.bin.path("playwright/browsers")
|
|
24
|
+
}
|
|
25
|
+
}, ondata)
|
|
26
|
+
await this.kernel.exec({
|
|
27
|
+
message: [
|
|
28
|
+
// "npm init -y",
|
|
29
|
+
"playwright install firefox",
|
|
30
|
+
],
|
|
31
|
+
//path: this.kernel.bin.path("playwright"),
|
|
32
|
+
env: {
|
|
33
|
+
PLAYWRIGHT_BROWSERS_PATH: this.kernel.bin.path("playwright/browsers")
|
|
34
|
+
}
|
|
35
|
+
}, ondata)
|
|
36
|
+
// await this.kernel.exec({
|
|
37
|
+
// message: [
|
|
38
|
+
// "npm init -y",
|
|
39
|
+
// "npm install @playwright/browser-chromium@1.47.0",
|
|
40
|
+
// "npm install @playwright/browser-firefox@1.47.0",
|
|
41
|
+
// "npm install @playwright/browser-webkit@1.47.0"
|
|
42
|
+
//// "npx playwright install chromium"
|
|
43
|
+
// ],
|
|
44
|
+
// path: this.kernel.bin.path("playwright"),
|
|
45
|
+
// env: {
|
|
46
|
+
// PLAYWRIGHT_BROWSERS_PATH: this.kernel.bin.path("playwright/browsers")
|
|
47
|
+
// }
|
|
48
|
+
// }, ondata)
|
|
49
|
+
await this.kernel.exec({
|
|
50
|
+
message: [
|
|
51
|
+
"pip install playwright==1.48.0",
|
|
52
|
+
// "playwright install"
|
|
53
|
+
// "npm install playwright --ignore-scripts"
|
|
54
|
+
],
|
|
55
|
+
env: {
|
|
56
|
+
PLAYWRIGHT_BROWSERS_PATH: this.kernel.bin.path("playwright/browsers")
|
|
57
|
+
}
|
|
58
|
+
}, ondata)
|
|
59
|
+
|
|
60
|
+
let pwpath = this.kernel.bin.path("miniconda/lib/node_modules/playwright")
|
|
61
|
+
process.env.PLAYWRIGHT_BROWSERS_PATH = this.kernel.bin.path("playwright/browsers")
|
|
62
|
+
this.kernel.playwright = (await this.kernel.loader.load(pwpath)).resolved
|
|
63
|
+
}
|
|
64
|
+
async installed() {
|
|
65
|
+
let p = this.kernel.bin.path("playwright/browsers")
|
|
66
|
+
let e = await this.kernel.bin.exists(p)
|
|
67
|
+
return e
|
|
68
|
+
}
|
|
69
|
+
async uninstall(req, ondata) {
|
|
70
|
+
ondata({ raw: "cleaning up\r\n" })
|
|
71
|
+
const folder = this.kernel.bin.path("playwright")
|
|
72
|
+
await rimraf(folder)
|
|
73
|
+
ondata({ raw: "finished cleaning up\r\n" })
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
module.exports = Playwright
|
package/kernel/index.js
CHANGED
|
@@ -35,7 +35,8 @@ const VARS = {
|
|
|
35
35
|
//const memwatch = require('@airbnb/node-memwatch');
|
|
36
36
|
class Kernel {
|
|
37
37
|
//schema = ">=1.0.0"
|
|
38
|
-
schema = "<=2.1.0"
|
|
38
|
+
//schema = "<=2.1.0"
|
|
39
|
+
schema = "<=2.2.0"
|
|
39
40
|
constructor(store) {
|
|
40
41
|
this.fetch = fetch
|
|
41
42
|
this.store = store
|
|
@@ -222,6 +223,26 @@ class Kernel {
|
|
|
222
223
|
await waitOn(options)
|
|
223
224
|
}
|
|
224
225
|
|
|
226
|
+
async synchronize_proxies() {
|
|
227
|
+
let proxy_registry_path = path.resolve(this.homedir, "proxy_registry")
|
|
228
|
+
let exists = await this.exists(proxy_registry_path)
|
|
229
|
+
if (exists) {
|
|
230
|
+
await this.exec({
|
|
231
|
+
message: "git pull",
|
|
232
|
+
path: proxy_registry_path,
|
|
233
|
+
}, (e) => {
|
|
234
|
+
process.stdout.write(e.raw)
|
|
235
|
+
})
|
|
236
|
+
} else {
|
|
237
|
+
await this.exec({
|
|
238
|
+
message: "git clone https://github.com/pinokiocomputer/proxy_registry"
|
|
239
|
+
path: this.homedir
|
|
240
|
+
}, (e) => {
|
|
241
|
+
process.stdout.write(e.raw)
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
225
246
|
async init(options) {
|
|
226
247
|
let home = this.store.get("home")
|
|
227
248
|
|
|
@@ -337,13 +358,18 @@ class Kernel {
|
|
|
337
358
|
system,
|
|
338
359
|
platform: this.platform,
|
|
339
360
|
arch: this.arch,
|
|
361
|
+
proxy: (port) => {
|
|
362
|
+
return this.api.get_proxy_url("/proxy", port)
|
|
363
|
+
},
|
|
340
364
|
...info
|
|
341
365
|
})
|
|
342
366
|
await this.update_sysinfo()
|
|
343
367
|
}
|
|
344
368
|
|
|
345
369
|
|
|
346
|
-
|
|
370
|
+
let pwpath = this.bin.path("miniconda/lib/node_modules/playwright")
|
|
371
|
+
process.env.PLAYWRIGHT_BROWSERS_PATH = this.bin.path("playwright/browsers")
|
|
372
|
+
this.playwright = (await this.loader.load(pwpath)).resolved
|
|
347
373
|
|
|
348
374
|
// await this.template.init()
|
|
349
375
|
|
package/kernel/lproxy.js
CHANGED
|
@@ -16,6 +16,7 @@ const proxies = proxy.all()
|
|
|
16
16
|
*/
|
|
17
17
|
const httpProxy = require('http-proxy');
|
|
18
18
|
const portfinder = require('portfinder-cp');
|
|
19
|
+
const cors = require('cors')
|
|
19
20
|
const os = require('os')
|
|
20
21
|
class Lproxy {
|
|
21
22
|
constructor() {
|
|
@@ -32,23 +33,47 @@ class Lproxy {
|
|
|
32
33
|
let o = Object.assign({
|
|
33
34
|
target: url,
|
|
34
35
|
ws: true,
|
|
35
|
-
|
|
36
|
+
changeOrigin: true,
|
|
37
|
+
// localAddress: '0.0.0.0',
|
|
36
38
|
}, options)
|
|
37
39
|
console.log("proxy object", o)
|
|
38
40
|
const proxy = httpProxy.createProxyServer(o)
|
|
41
|
+
|
|
39
42
|
// get a new port
|
|
40
43
|
if (!port) {
|
|
41
44
|
port = await portfinder.getPortPromise({
|
|
42
45
|
//port: 42420
|
|
43
|
-
port:
|
|
46
|
+
port: 50000
|
|
47
|
+
//port: 44000
|
|
44
48
|
})
|
|
45
49
|
}
|
|
46
50
|
proxy.listen(port)
|
|
47
51
|
proxy.on('close', (res, socket, head) => {
|
|
48
52
|
console.log('Client disconnected');
|
|
49
53
|
});
|
|
50
|
-
proxy.on(
|
|
51
|
-
|
|
54
|
+
proxy.on("error", function (err, req, res) {
|
|
55
|
+
res.writeHead(500, {
|
|
56
|
+
'Content-Type': 'text/plain',
|
|
57
|
+
});
|
|
58
|
+
res.end(err.stack)
|
|
59
|
+
});
|
|
60
|
+
proxy.on('proxyRes', (proxyRes, req, res) => {
|
|
61
|
+
console.log("proxyRes", { proxyRes, req, res })
|
|
62
|
+
if (req.headers.origin) {
|
|
63
|
+
res.setHeader('access-control-allow-origin', req.headers.origin);
|
|
64
|
+
}
|
|
65
|
+
res.setHeader('access-control-allow-credentials', 'true');
|
|
66
|
+
if (req.headers['access-control-request-method']) {
|
|
67
|
+
res.setHeader('access-control-allow-methods', req.headers['access-control-request-method']);
|
|
68
|
+
}
|
|
69
|
+
if (req.headers['access-control-request-headers']) {
|
|
70
|
+
res.setHeader('access-control-allow-headers', req.headers['access-control-request-headers']);
|
|
71
|
+
}
|
|
72
|
+
res.setHeader('access-control-max-age', 60 * 60 * 24 * 30);
|
|
73
|
+
if (req.method === 'OPTIONS') {
|
|
74
|
+
res.send(200);
|
|
75
|
+
res.end();
|
|
76
|
+
}
|
|
52
77
|
});
|
|
53
78
|
|
|
54
79
|
this.proxies[url] = proxy
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -449,6 +449,10 @@ class Server {
|
|
|
449
449
|
name: "py"
|
|
450
450
|
}, {
|
|
451
451
|
name: "cloudflared"
|
|
452
|
+
}, {
|
|
453
|
+
name: "playwright"
|
|
454
|
+
}, {
|
|
455
|
+
name: "huggingface"
|
|
452
456
|
}])
|
|
453
457
|
|
|
454
458
|
let requirements_pending = !this.kernel.bin.installed_initialized
|
|
@@ -722,6 +726,10 @@ class Server {
|
|
|
722
726
|
name: "py"
|
|
723
727
|
}, {
|
|
724
728
|
name: "cloudflared"
|
|
729
|
+
}, {
|
|
730
|
+
name: "playwright"
|
|
731
|
+
}, {
|
|
732
|
+
name: "huggingface"
|
|
725
733
|
}])
|
|
726
734
|
// if (platform === "linux") {
|
|
727
735
|
// requirements.push({
|
|
@@ -1138,6 +1146,7 @@ class Server {
|
|
|
1138
1146
|
if (this.cloudflare_pub) {
|
|
1139
1147
|
qr_cloudflare = await QRCode.toDataURL(this.cloudflare_pub)
|
|
1140
1148
|
}
|
|
1149
|
+
console.log("****************", { items })
|
|
1141
1150
|
|
|
1142
1151
|
res.render("index", {
|
|
1143
1152
|
home_url: `http://localhost:${this.port}`,
|
|
@@ -2115,11 +2124,12 @@ class Server {
|
|
|
2115
2124
|
icon: "ollama.webp",
|
|
2116
2125
|
name: "Ollama",
|
|
2117
2126
|
target: 'http://127.0.0.1:11434',
|
|
2118
|
-
port:
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2127
|
+
port: 44002
|
|
2128
|
+
}, {
|
|
2129
|
+
icon: "lmstudio.jpg",
|
|
2130
|
+
name: "LMStudio",
|
|
2131
|
+
target: 'http://127.0.0.1:1234',
|
|
2132
|
+
port: 44003
|
|
2123
2133
|
}]
|
|
2124
2134
|
for(let i=0; i<proxies.length; i++) {
|
|
2125
2135
|
proxies[i].running = false
|
|
@@ -2150,6 +2160,30 @@ class Server {
|
|
|
2150
2160
|
icon = "pinokio-black.png"
|
|
2151
2161
|
}
|
|
2152
2162
|
|
|
2163
|
+
|
|
2164
|
+
// App sharing
|
|
2165
|
+
let apipath = this.kernel.path("api")
|
|
2166
|
+
let files = await fs.promises.readdir(apipath, { withFileTypes: true })
|
|
2167
|
+
let folders = files.filter((f) => {
|
|
2168
|
+
return f.isDirectory()
|
|
2169
|
+
}).map((x) => {
|
|
2170
|
+
return x.name
|
|
2171
|
+
})
|
|
2172
|
+
let apps = []
|
|
2173
|
+
for(let folder of folders) {
|
|
2174
|
+
let p = path.resolve(apipath, folder, "pinokio.js")
|
|
2175
|
+
let pinokio = (await this.kernel.loader.load(p)).resolved
|
|
2176
|
+
if (pinokio) {
|
|
2177
|
+
apps.push({
|
|
2178
|
+
name: pinokio.title,
|
|
2179
|
+
description: pinokio.description,
|
|
2180
|
+
link: `/pinokio/browser/${folder}/browse#n1`,
|
|
2181
|
+
icon: pinokio.icon ? `/api/${folder}/${pinokio.icon}?raw=true` : null
|
|
2182
|
+
})
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
console.log({ apps })
|
|
2186
|
+
|
|
2153
2187
|
res.render("proxy", {
|
|
2154
2188
|
agent: this.agent,
|
|
2155
2189
|
theme: this.theme,
|
|
@@ -2157,7 +2191,8 @@ class Server {
|
|
|
2157
2191
|
qr,
|
|
2158
2192
|
proxy: home_proxy,
|
|
2159
2193
|
localhost: `http://localhost:${this.port}`,
|
|
2160
|
-
icon
|
|
2194
|
+
icon,
|
|
2195
|
+
apps
|
|
2161
2196
|
})
|
|
2162
2197
|
}))
|
|
2163
2198
|
this.app.post("/proxy", ex(async (req, res) => {
|
|
@@ -2228,7 +2263,7 @@ class Server {
|
|
|
2228
2263
|
await this.kernel.api.startProxy("/", `http://127.0.0.1:${this.port}`, "/")
|
|
2229
2264
|
}
|
|
2230
2265
|
} else {
|
|
2231
|
-
await this.kernel.api.startProxy("/", `http://127.0.0.1:${this.port}`, "/")
|
|
2266
|
+
await this.kernel.api.startProxy("/", `http://127.0.0.1:${this.port}`, "/", { port: 44001 })
|
|
2232
2267
|
}
|
|
2233
2268
|
console.log("started proxy")
|
|
2234
2269
|
} else if (req.body.type === "cloudflare") {
|
|
@@ -2286,6 +2321,9 @@ class Server {
|
|
|
2286
2321
|
const items = await Util.parse_env_detail(filepath)
|
|
2287
2322
|
let p = path.resolve(this.kernel.homedir, env_path, "pinokio.js")
|
|
2288
2323
|
let config = (await this.kernel.loader.load(p)).resolved
|
|
2324
|
+
|
|
2325
|
+
|
|
2326
|
+
console.log(">>>>>>>>>>>>>>>>>", { config })
|
|
2289
2327
|
if (config.icon) {
|
|
2290
2328
|
config.icon = `/${env_path}/${config.icon}?raw=true`
|
|
2291
2329
|
}
|
|
@@ -2295,6 +2333,35 @@ class Server {
|
|
|
2295
2333
|
name = env_path.split("/")[1]
|
|
2296
2334
|
}
|
|
2297
2335
|
|
|
2336
|
+
//if (config.run) {
|
|
2337
|
+
// let configStr = await fs.promises.readFile(p, "utf8")
|
|
2338
|
+
// res.render("disposable", {
|
|
2339
|
+
// home: null,
|
|
2340
|
+
// config,
|
|
2341
|
+
// name,
|
|
2342
|
+
// init: req.query ? req.query.init : null,
|
|
2343
|
+
// editorpath,
|
|
2344
|
+
// items,
|
|
2345
|
+
// theme: this.theme,
|
|
2346
|
+
// filepath,
|
|
2347
|
+
// agent: this.agent,
|
|
2348
|
+
// path: "/api/" + name + "/pinokio.js",
|
|
2349
|
+
// _path: "/_api/" + name,
|
|
2350
|
+
// str: configStr
|
|
2351
|
+
// })
|
|
2352
|
+
//} else {
|
|
2353
|
+
// res.render("env_editor", {
|
|
2354
|
+
// home: null,
|
|
2355
|
+
// config,
|
|
2356
|
+
// name,
|
|
2357
|
+
// init: req.query ? req.query.init : null,
|
|
2358
|
+
// editorpath,
|
|
2359
|
+
// items,
|
|
2360
|
+
// theme: this.theme,
|
|
2361
|
+
// filepath,
|
|
2362
|
+
// agent: this.agent,
|
|
2363
|
+
// })
|
|
2364
|
+
//}
|
|
2298
2365
|
res.render("env_editor", {
|
|
2299
2366
|
home: null,
|
|
2300
2367
|
config,
|
|
@@ -2306,6 +2373,7 @@ class Server {
|
|
|
2306
2373
|
filepath,
|
|
2307
2374
|
agent: this.agent,
|
|
2308
2375
|
})
|
|
2376
|
+
|
|
2309
2377
|
}))
|
|
2310
2378
|
this.app.get("/pre/api/:name", ex(async (req, res) => {
|
|
2311
2379
|
let p = path.resolve(this.kernel.homedir, "api", req.params.name, "pinokio.js")
|
|
Binary file
|
package/server/public/style.css
CHANGED
|
@@ -1618,9 +1618,10 @@ footer.status {
|
|
|
1618
1618
|
flex-grow: 1;
|
|
1619
1619
|
}
|
|
1620
1620
|
#error-screen-footer {
|
|
1621
|
+
display: flex;
|
|
1621
1622
|
padding: 10px;
|
|
1622
1623
|
box-sizing: border-box;
|
|
1623
|
-
text-align:
|
|
1624
|
+
text-align: right;
|
|
1624
1625
|
background: royalblue;
|
|
1625
1626
|
}
|
|
1626
1627
|
#error-screen-close {
|
|
@@ -1640,7 +1641,10 @@ footer.status {
|
|
|
1640
1641
|
padding: 15px 30px;
|
|
1641
1642
|
font-weight: bold;
|
|
1642
1643
|
background: firebrick;
|
|
1644
|
+
/*
|
|
1643
1645
|
border-radius: 50px;
|
|
1646
|
+
*/
|
|
1647
|
+
margin: 5px;
|
|
1644
1648
|
text-transform: uppercase;
|
|
1645
1649
|
}
|
|
1646
1650
|
|
|
@@ -1651,3 +1655,10 @@ mark{
|
|
|
1651
1655
|
display: inline-block;
|
|
1652
1656
|
margin: 5px 0;
|
|
1653
1657
|
}
|
|
1658
|
+
#close-error-screen {
|
|
1659
|
+
border-radius: 50px;
|
|
1660
|
+
background: white !important;
|
|
1661
|
+
padding: 15px !important;
|
|
1662
|
+
color: royalblue !important;
|
|
1663
|
+
cursor: pointer;
|
|
1664
|
+
}
|
|
@@ -590,7 +590,7 @@ body.dark .loader-container {
|
|
|
590
590
|
</div>
|
|
591
591
|
-->
|
|
592
592
|
<div class='grid-btns'>
|
|
593
|
-
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-
|
|
593
|
+
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
594
594
|
<button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Debug</div></button>
|
|
595
595
|
<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>
|
|
596
596
|
<a class='btn2' href="/"><div><i class="fa-solid fa-house"></i></div><div>Home</div></a>
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
<html class='columns'>
|
|
2
|
+
<head>
|
|
3
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
|
4
|
+
<script src="/hotkeys.min.js"></script>
|
|
5
|
+
<script src="/ace/ace.js"></script>
|
|
6
|
+
<script src="/noty.js"></script>
|
|
7
|
+
<script src="/notyq.js"></script>
|
|
8
|
+
<script src="/xterm.js"></script>
|
|
9
|
+
<script src="/xterm-addon-fit.js"></script>
|
|
10
|
+
<script src="/xterm-addon-web-links.js"></script>
|
|
11
|
+
<script src="/xterm-theme.js"></script>
|
|
12
|
+
<script src="/xterm-addon-search.js"></script>
|
|
13
|
+
<script src="/xterm-addon-search-bar.js"></script>
|
|
14
|
+
<script src="/sweetalert2.js"></script>
|
|
15
|
+
<script src="/Socket.js"></script>
|
|
16
|
+
<script src="/common.js"></script>
|
|
17
|
+
<script src="/he.js"></script>
|
|
18
|
+
<script src="/opener.js"></script>
|
|
19
|
+
<script src="/nav.js"></script>
|
|
20
|
+
<script src="/autoexpand.js"></script>
|
|
21
|
+
<script src="/modalinput.js"></script>
|
|
22
|
+
<script src="/simplemodal.js"></script>
|
|
23
|
+
<script src="/waitmodal.js"></script>
|
|
24
|
+
<script src="/notifyinput.js"></script>
|
|
25
|
+
<script src="/report.js"></script>
|
|
26
|
+
<link href="/xterm.min.css" rel="stylesheet" />
|
|
27
|
+
<link href="/css/fontawesome.min.css" rel="stylesheet">
|
|
28
|
+
<link href="/css/solid.min.css" rel="stylesheet">
|
|
29
|
+
<link href="/css/regular.min.css" rel="stylesheet">
|
|
30
|
+
<link href="/css/brands.min.css" rel="stylesheet">
|
|
31
|
+
<link href="/style.css" rel="stylesheet"/>
|
|
32
|
+
<link href="/noty.css" rel="stylesheet"/>
|
|
33
|
+
<% if (agent === "electron") { %>
|
|
34
|
+
<link href="/electron.css" rel="stylesheet"/>
|
|
35
|
+
<% } %>
|
|
36
|
+
<style>
|
|
37
|
+
body.frozen {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
height: 100%;
|
|
41
|
+
}
|
|
42
|
+
#table > table {
|
|
43
|
+
border-left: 2px solid black;
|
|
44
|
+
padding-left: 5px;
|
|
45
|
+
margin: 10px 0;
|
|
46
|
+
}
|
|
47
|
+
.highlight {
|
|
48
|
+
background: yellow;
|
|
49
|
+
width: 100px;
|
|
50
|
+
}
|
|
51
|
+
th {
|
|
52
|
+
background: rgba(0,0,0,0.1);
|
|
53
|
+
padding: 10px;
|
|
54
|
+
font-size: 12px;
|
|
55
|
+
}
|
|
56
|
+
td {
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
padding: 10px;
|
|
59
|
+
}
|
|
60
|
+
td.val {
|
|
61
|
+
background: rgba(0,0,0,0.06);
|
|
62
|
+
}
|
|
63
|
+
td.key {
|
|
64
|
+
background: rgba(0,0,0,0.1);
|
|
65
|
+
}
|
|
66
|
+
.button {
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
background: rgba(0,0,0,0.8);
|
|
69
|
+
color: white;
|
|
70
|
+
padding: 5px 10px;
|
|
71
|
+
border-radius: 4px;
|
|
72
|
+
}
|
|
73
|
+
.button:hover {
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
<% if (init) { %>
|
|
77
|
+
main {
|
|
78
|
+
width: 100%;
|
|
79
|
+
box-sizing: border-box;
|
|
80
|
+
max-width: 600px;
|
|
81
|
+
padding: 20px;
|
|
82
|
+
margin: 0 auto;
|
|
83
|
+
}
|
|
84
|
+
<% } else { %>
|
|
85
|
+
#editor {
|
|
86
|
+
width: 100%;
|
|
87
|
+
box-sizing: border-box;
|
|
88
|
+
max-width: 600px;
|
|
89
|
+
padding: 20px;
|
|
90
|
+
margin: 0 auto;
|
|
91
|
+
}
|
|
92
|
+
<% } %>
|
|
93
|
+
|
|
94
|
+
header .btn {
|
|
95
|
+
font-family: Sans-serif;
|
|
96
|
+
display: block;
|
|
97
|
+
margin-left: 10px;
|
|
98
|
+
font-style: normal;
|
|
99
|
+
font-size: 12px;
|
|
100
|
+
font-weight: normal;
|
|
101
|
+
padding: 5px 10px;
|
|
102
|
+
}
|
|
103
|
+
.disabled {
|
|
104
|
+
opacity: 0.7;
|
|
105
|
+
}
|
|
106
|
+
body.dark .env-item input[type=text] {
|
|
107
|
+
background: white;
|
|
108
|
+
}
|
|
109
|
+
.env-item input[type=text] {
|
|
110
|
+
width: 100%;
|
|
111
|
+
padding: 10px;
|
|
112
|
+
box-sizing: border-box;
|
|
113
|
+
border: none;
|
|
114
|
+
background: rgba(0,0,100, 0.1);
|
|
115
|
+
}
|
|
116
|
+
body.dark .env-item label {
|
|
117
|
+
color: cornflowerblue;
|
|
118
|
+
}
|
|
119
|
+
.env-item label {
|
|
120
|
+
color: royalblue;
|
|
121
|
+
display: block;
|
|
122
|
+
margin-bottom: 5px;
|
|
123
|
+
font-weight: bold;
|
|
124
|
+
font-size: 18px;
|
|
125
|
+
}
|
|
126
|
+
.env-item {
|
|
127
|
+
padding-top: 10px;
|
|
128
|
+
padding-bottom: 30px;
|
|
129
|
+
}
|
|
130
|
+
body.dark .comment {
|
|
131
|
+
border-left: 2px solid white;
|
|
132
|
+
}
|
|
133
|
+
.comment {
|
|
134
|
+
opacity: 0.8;
|
|
135
|
+
border-left: 2px solid black;
|
|
136
|
+
padding-left: 10px;
|
|
137
|
+
}
|
|
138
|
+
#save {
|
|
139
|
+
background: royalblue;
|
|
140
|
+
}
|
|
141
|
+
a#customize {
|
|
142
|
+
text-decoration: none;
|
|
143
|
+
cursor: pointer;
|
|
144
|
+
}
|
|
145
|
+
.e {
|
|
146
|
+
padding: 10px 0;
|
|
147
|
+
}
|
|
148
|
+
#editor {
|
|
149
|
+
padding: 20px 0;
|
|
150
|
+
}
|
|
151
|
+
.center {
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
justify-content: center;
|
|
155
|
+
}
|
|
156
|
+
body {
|
|
157
|
+
display: block;
|
|
158
|
+
}
|
|
159
|
+
.card {
|
|
160
|
+
display: flex;
|
|
161
|
+
padding: 10px 0;
|
|
162
|
+
box-sizing: border-box;
|
|
163
|
+
}
|
|
164
|
+
.card img {
|
|
165
|
+
width: 100px;
|
|
166
|
+
border-radius: 10px;
|
|
167
|
+
}
|
|
168
|
+
.card .description {
|
|
169
|
+
opacity: 0.8;
|
|
170
|
+
}
|
|
171
|
+
.card .title {
|
|
172
|
+
font-weight: bold;
|
|
173
|
+
font-size: 30px;
|
|
174
|
+
letter-spacing: -1px;
|
|
175
|
+
}
|
|
176
|
+
.card .col {
|
|
177
|
+
padding-left: 10px;
|
|
178
|
+
}
|
|
179
|
+
h1 {
|
|
180
|
+
font-size: 50px;
|
|
181
|
+
font-family: georgia;
|
|
182
|
+
font-style: italic;
|
|
183
|
+
padding-bottom: 20px;
|
|
184
|
+
}
|
|
185
|
+
footer {
|
|
186
|
+
background: none;
|
|
187
|
+
padding: 0;
|
|
188
|
+
text-align: right;
|
|
189
|
+
display: flex;
|
|
190
|
+
margin: 10px 0 20px 0;
|
|
191
|
+
}
|
|
192
|
+
footer .btn {
|
|
193
|
+
margin-left: 10px;
|
|
194
|
+
display: inline-block;
|
|
195
|
+
-webkit-appearance: button;
|
|
196
|
+
-moz-appearance: button;
|
|
197
|
+
appearance: button;
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
footer .btn.go-home {
|
|
201
|
+
margin-left: 0px;
|
|
202
|
+
}
|
|
203
|
+
.btn.home-button {
|
|
204
|
+
background: none !important;
|
|
205
|
+
margin: 0 !important;
|
|
206
|
+
font-size: 16px !important;
|
|
207
|
+
}
|
|
208
|
+
#editor {
|
|
209
|
+
height: auto;
|
|
210
|
+
}
|
|
211
|
+
</style>
|
|
212
|
+
<script>
|
|
213
|
+
document.addEventListener("DOMContentLoaded", async () => {
|
|
214
|
+
const n = new N()
|
|
215
|
+
document.querySelector("#save").addEventListener("click", async (e) => {
|
|
216
|
+
// save
|
|
217
|
+
const vals = {}
|
|
218
|
+
const els = document.querySelectorAll(".env-item")
|
|
219
|
+
for(let el of els) {
|
|
220
|
+
let input = el.querySelector("input[type=text]")
|
|
221
|
+
vals[input.id] = input.value
|
|
222
|
+
}
|
|
223
|
+
console.log("vals", vals)
|
|
224
|
+
let res = await fetch("/env", {
|
|
225
|
+
method: "POST",
|
|
226
|
+
headers: {
|
|
227
|
+
"Content-Type": "application/json"
|
|
228
|
+
},
|
|
229
|
+
body: JSON.stringify({
|
|
230
|
+
filepath: location.pathname.slice(5),
|
|
231
|
+
vals
|
|
232
|
+
})
|
|
233
|
+
}).then((res) => {
|
|
234
|
+
return res.json()
|
|
235
|
+
})
|
|
236
|
+
console.log("res" ,res)
|
|
237
|
+
<% if (init && name) { %>
|
|
238
|
+
location.href = "/pinokio/browser/<%=name%>"
|
|
239
|
+
<% } else { %>
|
|
240
|
+
n.Noty({
|
|
241
|
+
text: `Updated!`
|
|
242
|
+
})
|
|
243
|
+
<% } %>
|
|
244
|
+
})
|
|
245
|
+
<% if (init) { %>
|
|
246
|
+
/*
|
|
247
|
+
document.querySelector("#customize").addEventListener("click", (e) => {
|
|
248
|
+
e.preventDefault()
|
|
249
|
+
e.stopPropagation()
|
|
250
|
+
document.querySelector("#editor").classList.toggle("hidden")
|
|
251
|
+
})
|
|
252
|
+
let editor = ace.edit("editor");
|
|
253
|
+
editor.setTheme("ace/theme/nord_dark");
|
|
254
|
+
editor.setOptions({
|
|
255
|
+
maxLines: Infinity, // set to a large number
|
|
256
|
+
minLines: 1 // set to a small number
|
|
257
|
+
});
|
|
258
|
+
editor.session.setMode("ace/mode/javascript");
|
|
259
|
+
editor.clearSelection()
|
|
260
|
+
*/
|
|
261
|
+
<% } %>
|
|
262
|
+
})
|
|
263
|
+
</script>
|
|
264
|
+
</head>
|
|
265
|
+
<body class='<%=theme%> <%=init ? 'center' : ''%>'>
|
|
266
|
+
<main>
|
|
267
|
+
<% if (init) { %>
|
|
268
|
+
<div>
|
|
269
|
+
<h1>Run</h1>
|
|
270
|
+
<% if (config) { %>
|
|
271
|
+
<div class='card'>
|
|
272
|
+
<% if (config.icon) { %>
|
|
273
|
+
<img src="<%=config.icon%>">
|
|
274
|
+
<% } %>
|
|
275
|
+
<div class='col'>
|
|
276
|
+
<div class='title'><%=config.title%></div>
|
|
277
|
+
<div class='description'><%=config.description%></div>
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
<% } %>
|
|
281
|
+
<footer>
|
|
282
|
+
<a href="/" class='btn go-home'><i class='fa-solid fa-home'></i> home</a>
|
|
283
|
+
<div class='flexible'></div>
|
|
284
|
+
<a id='customize' class='btn' target="_blank" href='<%=_path%>'><i class='fa-solid fa-code'></i> View Script</a>
|
|
285
|
+
<!--
|
|
286
|
+
<button id='customize' class='btn'><i class="fa-solid fa-code"></i> View Script</button>
|
|
287
|
+
-->
|
|
288
|
+
<a id='save' href="<%=path%>" class='btn'>
|
|
289
|
+
<span class='save'><i class="fa-solid fa-check"></i> Run</span>
|
|
290
|
+
</a>
|
|
291
|
+
</footer>
|
|
292
|
+
</div>
|
|
293
|
+
<% } else { %>
|
|
294
|
+
<header class='navheader grabbable'>
|
|
295
|
+
<h1>
|
|
296
|
+
<% if (home) { %>
|
|
297
|
+
<a class='home-button home' href="/"><i class='fa-solid fa-home'></i></a>
|
|
298
|
+
<% } %>
|
|
299
|
+
<div class='flexible'></div>
|
|
300
|
+
<div class='nav-btns'>
|
|
301
|
+
<a class='btn' href="<%=editorpath%>"><i class="fa-solid fa-pen-to-square"></i> Edit file</a>
|
|
302
|
+
<button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> Open in File Explorer</button>
|
|
303
|
+
<div id='save' class='btn'>
|
|
304
|
+
<span class='save'><i class="fa-solid fa-check"></i> Save</span>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
</h1>
|
|
308
|
+
</header>
|
|
309
|
+
<% } %>
|
|
310
|
+
<div id='editor' class='<%=init ? "hidden" : ''%>'><%=str%></div>
|
|
311
|
+
</main>
|
|
312
|
+
</body>
|
|
313
|
+
</html>
|
package/server/views/editor.ejs
CHANGED
|
@@ -739,6 +739,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
739
739
|
}
|
|
740
740
|
})
|
|
741
741
|
}
|
|
742
|
+
document.querySelector("#close-error-screen").addEventListener('click', (e) => {
|
|
743
|
+
document.querySelector("#error-screen").classList.add("hidden")
|
|
744
|
+
})
|
|
742
745
|
})
|
|
743
746
|
const reloadMemory = async () => {
|
|
744
747
|
let url = "/pinokio/memory?filepath=" + encodeURI("<%-filepath%>")
|
|
@@ -888,8 +891,12 @@ const reloadMemory = async () => {
|
|
|
888
891
|
<div id='error-screen' class='hidden'>
|
|
889
892
|
<pre></pre>
|
|
890
893
|
<div id='error-screen-footer'>
|
|
894
|
+
<a class='btn' id='close-error-screen'>
|
|
895
|
+
<div><i class="fa-solid fa-xmark"></i></div>
|
|
896
|
+
</a>
|
|
897
|
+
<div class='flexible'></div>
|
|
891
898
|
<a class='btn' href="https://portal.pinokio.computer" target="_blank">
|
|
892
|
-
<div><i class="fa-solid fa-
|
|
899
|
+
<div><i class="fa-solid fa-question"></i> Ask Community</div>
|
|
893
900
|
</a>
|
|
894
901
|
</div>
|
|
895
902
|
</div>
|
package/server/views/explore.ejs
CHANGED
|
@@ -132,7 +132,7 @@ body main iframe {
|
|
|
132
132
|
<div class='flexible'></div>
|
|
133
133
|
<div class='nav-btns'>
|
|
134
134
|
<a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|
|
135
|
-
<a class='btn2' href="
|
|
135
|
+
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
136
136
|
<a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
|
|
137
137
|
<button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
|
|
138
138
|
</div>
|
|
@@ -703,6 +703,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
703
703
|
}
|
|
704
704
|
})
|
|
705
705
|
}
|
|
706
|
+
document.querySelector("#close-error-screen").addEventListener('click', (e) => {
|
|
707
|
+
document.querySelector("#error-screen").classList.add("hidden")
|
|
708
|
+
})
|
|
706
709
|
})
|
|
707
710
|
const reloadMemory = async () => {
|
|
708
711
|
let url = "/pinokio/memory?filepath=<%=encodedFilePath%>"
|
|
@@ -826,8 +829,12 @@ const reloadMemory = async () => {
|
|
|
826
829
|
<div id='error-screen' class='hidden'>
|
|
827
830
|
<pre></pre>
|
|
828
831
|
<div id='error-screen-footer'>
|
|
832
|
+
<a class='btn' id='close-error-screen'>
|
|
833
|
+
<div><i class="fa-solid fa-xmark"></i></div>
|
|
834
|
+
</a>
|
|
835
|
+
<div class='flexible'></div>
|
|
829
836
|
<a class='btn' href="https://portal.pinokio.computer" target="_blank">
|
|
830
|
-
<div><i class="fa-solid fa-
|
|
837
|
+
<div><i class="fa-solid fa-question"></i> Ask Community</div>
|
|
831
838
|
</a>
|
|
832
839
|
</div>
|
|
833
840
|
</div>
|
package/server/views/index.ejs
CHANGED
|
@@ -182,9 +182,8 @@ body.dark .browser-options-row {
|
|
|
182
182
|
</form>
|
|
183
183
|
<% if (ishome) { %>
|
|
184
184
|
<div class='nav-btns'>
|
|
185
|
-
<a class='btn2' href='/proxy'><div><i class="fa-solid fa-wifi"></i></div><div>Share</div></a>
|
|
186
185
|
<a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|
|
187
|
-
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-
|
|
186
|
+
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
188
187
|
<% if (agent === "electron") { %>
|
|
189
188
|
<a class='btn2' data-filepath="<%=filepath%>"><div><i class="fa-regular fa-folder-open"></i></div><div>Files</div></a>
|
|
190
189
|
<% } %>
|
|
@@ -236,6 +235,13 @@ body.dark .browser-options-row {
|
|
|
236
235
|
</div>
|
|
237
236
|
</div>
|
|
238
237
|
<% } %>
|
|
238
|
+
<div class='browser-options-row'>
|
|
239
|
+
<a href="/proxy" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
|
|
240
|
+
<div class='flexible'>
|
|
241
|
+
<h3><i class="fa-solid fa-wifi"></i> Local Sharing</h3>
|
|
242
|
+
<div>Serve Pinokio, installed apps, and even external apps (example: Ollama) to any device on the same network.</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
239
245
|
<!--
|
|
240
246
|
<div class='browser-options-row'>
|
|
241
247
|
<a href="/proxy" class='flexible'>
|
package/server/views/proxy.ejs
CHANGED
|
@@ -127,19 +127,48 @@ body.dark .browser-options-row {
|
|
|
127
127
|
text-decoration: none;
|
|
128
128
|
}
|
|
129
129
|
.line.align-top h3 {
|
|
130
|
+
/*
|
|
130
131
|
align-items: flex-start;
|
|
132
|
+
*/
|
|
133
|
+
align-items: center;
|
|
131
134
|
}
|
|
132
135
|
.line a:hover {
|
|
133
136
|
color: red;
|
|
134
137
|
}
|
|
138
|
+
.line img {
|
|
139
|
+
width: 40px;
|
|
140
|
+
height: 40px;
|
|
141
|
+
}
|
|
135
142
|
.btn-container {
|
|
136
143
|
margin-top: 10px;
|
|
137
144
|
}
|
|
138
145
|
.header-label {
|
|
139
|
-
font-
|
|
146
|
+
font-family: Georgia;
|
|
147
|
+
font-style: italic;
|
|
148
|
+
font-size: 50px;
|
|
140
149
|
letter-spacing: -1px;
|
|
141
|
-
padding:
|
|
150
|
+
padding: 50px;
|
|
142
151
|
text-align: center;
|
|
152
|
+
text-transform: capitalize;
|
|
153
|
+
}
|
|
154
|
+
.header-label-sub {
|
|
155
|
+
font-size: 25px;
|
|
156
|
+
letter-spacing: -1px;
|
|
157
|
+
padding: 15px;
|
|
158
|
+
font-weight: bold;
|
|
159
|
+
}
|
|
160
|
+
.container {
|
|
161
|
+
display: grid;
|
|
162
|
+
grid-template-columns: repeat(2, 1fr);
|
|
163
|
+
}
|
|
164
|
+
.dark .container-row {
|
|
165
|
+
background: rgba(255, 255, 255, 0.04);
|
|
166
|
+
}
|
|
167
|
+
.container-row {
|
|
168
|
+
margin: 10px;
|
|
169
|
+
background: rgba(0, 0, 100, 0.04);
|
|
170
|
+
padding: 20px;
|
|
171
|
+
box-sizing: border-box;
|
|
143
172
|
}
|
|
144
173
|
@media only screen and (max-width: 480px) {
|
|
145
174
|
.btn2 {
|
|
@@ -171,59 +200,72 @@ body.dark .browser-options-row {
|
|
|
171
200
|
</h1>
|
|
172
201
|
</header>
|
|
173
202
|
<main>
|
|
203
|
+
<div class='header-label'><i class='fa-solid fa-wifi'></i> Local Sharing</div>
|
|
174
204
|
<div class='container'>
|
|
175
|
-
<div class='
|
|
176
|
-
<div class='header-label'><i class=
|
|
177
|
-
<
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
|
|
205
|
+
<div class='container-row'>
|
|
206
|
+
<div class='header-label-sub'><i class="fa-solid fa-microchip"></i> System Programs</div>
|
|
207
|
+
<div class='line align-top'>
|
|
208
|
+
<h3>
|
|
209
|
+
<img class='icon' src="<%=icon%>">
|
|
210
|
+
<div class='col'>
|
|
211
|
+
<div class='title'>Pinokio</div>
|
|
212
|
+
<% if (proxy) { %>
|
|
213
|
+
<div class='description'><a href="<%=proxy.proxy%>" target="_blank"><%=proxy.proxy%></a> → <a href="<%=localhost%>" target="_blank"><%=localhost%></a></div>
|
|
214
|
+
<a class='wifi-qr badge' data-qr="<%=qr%>" data-url="<%=proxy.proxy%>"><i class="fa-solid fa-qrcode"></i> Scan QR Code</a>
|
|
215
|
+
<% } else { %>
|
|
216
|
+
<div class='description'>Share Pinokio <a href="<%=localhost%>" target="_blank"><%=localhost%></a> with other devices on the same network</div>
|
|
217
|
+
<% } %>
|
|
218
|
+
<div class='btn-container'>
|
|
219
|
+
<% if (proxy) { %>
|
|
220
|
+
<div id='wifi-stop' data-proxy="<%=proxy.proxy%>" class='btn'><div><i class="fa-solid fa-stop"></i> Stop</div></div>
|
|
221
|
+
<% } else { %>
|
|
222
|
+
<div id='wifi' class='btn'><div><i class="fa-solid fa-play"></i> Start at port 44001</div></div>
|
|
223
|
+
<div id='wifi-starting' class='btn disabled hidden'><div><i class="fa-solid fa-circle-notch fa-spin"></i> Starting</div></div>
|
|
224
|
+
<% } %>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
</h3>
|
|
228
|
+
</div>
|
|
229
|
+
<% items.forEach((item) => { %>
|
|
181
230
|
<div class='line align-top'>
|
|
182
231
|
<h3>
|
|
183
|
-
<img class='icon' src="<%=icon%>">
|
|
232
|
+
<img class='icon' src="<%=item.icon%>">
|
|
184
233
|
<div class='col'>
|
|
185
|
-
<div class='title'
|
|
186
|
-
<% if (proxy) { %>
|
|
187
|
-
<div class='description'><a href="<%=
|
|
188
|
-
<a class='wifi-qr badge' data-qr="<%=qr%>" data-url="<%=
|
|
234
|
+
<div class='title'><%=item.name%></div>
|
|
235
|
+
<% if (item.proxy) { %>
|
|
236
|
+
<div class='description'><a href="<%=item.proxy%>" target="_blank"><%=item.proxy%></a> → <a href="<%=item.target%>" target="_blank"><%=item.target%></a></div>
|
|
237
|
+
<a class='wifi-qr badge' data-qr="<%=item.qr%>" data-url="<%=item.proxy%>"><i class="fa-solid fa-qrcode"></i> Scan QR Code</a>
|
|
189
238
|
<% } else { %>
|
|
190
|
-
<div class='description'>Share
|
|
239
|
+
<div class='description'>Share <%=item.target%> with other devices on the same network</div>
|
|
191
240
|
<% } %>
|
|
192
241
|
<div class='btn-container'>
|
|
193
|
-
<% if (
|
|
194
|
-
<div
|
|
242
|
+
<% if (item.running) { %>
|
|
243
|
+
<div data-port="<%=item.port%>" data-name="<%=item.name%>" data-target="<%=item.target%>" class='stop btn'><i class="fa-solid fa-stop"></i> Stop</div>
|
|
195
244
|
<% } else { %>
|
|
196
|
-
<div
|
|
197
|
-
<div id='wifi-starting' class='btn disabled hidden'><div><i class="fa-solid fa-circle-notch fa-spin"></i> Starting</div></div>
|
|
245
|
+
<div data-port="<%=item.port%>" data-name="<%=item.name%>" data-target="<%=item.target%>" class='start btn'><i class="fa-solid fa-play"></i> Start at port <%=item.port%></div>
|
|
198
246
|
<% } %>
|
|
199
247
|
</div>
|
|
200
248
|
</div>
|
|
201
249
|
</h3>
|
|
202
250
|
</div>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
</div>
|
|
222
|
-
</div>
|
|
223
|
-
</h3>
|
|
224
|
-
</div>
|
|
225
|
-
<% }) %>
|
|
226
|
-
</div>
|
|
251
|
+
<% }) %>
|
|
252
|
+
</div>
|
|
253
|
+
<div class='container-row'>
|
|
254
|
+
<div class='header-label-sub'><i class="fa-solid fa-dice-d6"></i> Application Programs</div>
|
|
255
|
+
<% apps.forEach((item) => { %>
|
|
256
|
+
<a class='line align-top' href="<%=item.link%>">
|
|
257
|
+
<h3>
|
|
258
|
+
<img class='icon' src="<%=item.icon%>">
|
|
259
|
+
<div class='col'>
|
|
260
|
+
<div class='title'><%=item.name%></div>
|
|
261
|
+
<div class='description'><%=item.description%></div>
|
|
262
|
+
</div>
|
|
263
|
+
<div class='spinner'>
|
|
264
|
+
<i class="fa-solid fa-chevron-right"></i>
|
|
265
|
+
</div>
|
|
266
|
+
</h3>
|
|
267
|
+
</a>
|
|
268
|
+
<% }) %>
|
|
227
269
|
</div>
|
|
228
270
|
</div>
|
|
229
271
|
</main>
|
|
@@ -234,7 +234,7 @@ hr {
|
|
|
234
234
|
<div class='flexible'></div>
|
|
235
235
|
<div class='nav-btns'>
|
|
236
236
|
<a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|
|
237
|
-
<a class='btn2' href="
|
|
237
|
+
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
238
238
|
<a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
|
|
239
239
|
<button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
|
|
240
240
|
</div>
|