pinokiod 2.15.42 → 2.15.43
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/package.json +1 -1
- package/server/index.js +62 -35
- package/server/views/file_explorer.ejs +1083 -0
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -602,8 +602,6 @@ class Server {
|
|
|
602
602
|
let json
|
|
603
603
|
let js
|
|
604
604
|
|
|
605
|
-
console.log("filepath", filepath)
|
|
606
|
-
|
|
607
605
|
if (filepath.endsWith(".json")) {
|
|
608
606
|
try {
|
|
609
607
|
json = (await this.kernel.loader.load(filepath)).resolved
|
|
@@ -1305,9 +1303,7 @@ class Server {
|
|
|
1305
1303
|
}
|
|
1306
1304
|
|
|
1307
1305
|
// custom theme
|
|
1308
|
-
console.log(this.kernel.path('web'))
|
|
1309
1306
|
let exists = await fse.pathExists(this.kernel.path("web"))
|
|
1310
|
-
console.log("Exists", exists)
|
|
1311
1307
|
if (exists) {
|
|
1312
1308
|
let config_exists = await fse.pathExists(this.kernel.path("web/config.json"))
|
|
1313
1309
|
if (config_exists) {
|
|
@@ -1321,35 +1317,68 @@ class Server {
|
|
|
1321
1317
|
}
|
|
1322
1318
|
}
|
|
1323
1319
|
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1320
|
+
if (meta) {
|
|
1321
|
+
res.render("index", {
|
|
1322
|
+
home_url: `http://localhost:${this.port}`,
|
|
1323
|
+
proxy: home_proxy,
|
|
1324
|
+
cloudflare_pub: this.cloudflare_pub,
|
|
1325
|
+
qr,
|
|
1326
|
+
qr_cloudflare,
|
|
1327
|
+
error: error,
|
|
1328
|
+
logo: this.logo,
|
|
1329
|
+
// memory: mem,
|
|
1330
|
+
theme: this.theme,
|
|
1331
|
+
pinokioPath,
|
|
1332
|
+
config,
|
|
1333
|
+
display,
|
|
1334
|
+
agent: this.agent,
|
|
1335
|
+
// folder,
|
|
1336
|
+
paths,
|
|
1337
|
+
uri,
|
|
1338
|
+
gitRemote,
|
|
1339
|
+
userdir: this.kernel.api.userdir,
|
|
1340
|
+
ishome: meta,
|
|
1341
|
+
running,
|
|
1342
|
+
notRunning,
|
|
1343
|
+
readme,
|
|
1344
|
+
filepath,
|
|
1345
|
+
mode: null,
|
|
1346
|
+
kernel: this.kernel,
|
|
1347
|
+
//mode: (req.query && req.query.mode ? req.query.mode : null),
|
|
1348
|
+
items
|
|
1349
|
+
})
|
|
1350
|
+
} else {
|
|
1351
|
+
res.render("file_explorer", {
|
|
1352
|
+
home_url: `http://localhost:${this.port}`,
|
|
1353
|
+
proxy: home_proxy,
|
|
1354
|
+
cloudflare_pub: this.cloudflare_pub,
|
|
1355
|
+
qr,
|
|
1356
|
+
qr_cloudflare,
|
|
1357
|
+
error: error,
|
|
1358
|
+
logo: this.logo,
|
|
1359
|
+
// memory: mem,
|
|
1360
|
+
theme: this.theme,
|
|
1361
|
+
pinokioPath,
|
|
1362
|
+
config,
|
|
1363
|
+
display,
|
|
1364
|
+
agent: this.agent,
|
|
1365
|
+
// folder,
|
|
1366
|
+
paths,
|
|
1367
|
+
uri,
|
|
1368
|
+
gitRemote,
|
|
1369
|
+
userdir: this.kernel.api.userdir,
|
|
1370
|
+
ishome: meta,
|
|
1371
|
+
running,
|
|
1372
|
+
notRunning,
|
|
1373
|
+
readme,
|
|
1374
|
+
filepath,
|
|
1375
|
+
mode: null,
|
|
1376
|
+
kernel: this.kernel,
|
|
1377
|
+
//mode: (req.query && req.query.mode ? req.query.mode : null),
|
|
1378
|
+
items
|
|
1379
|
+
})
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1353
1382
|
}
|
|
1354
1383
|
}
|
|
1355
1384
|
async renderShortcuts(uri, name, config, pathComponents) {
|
|
@@ -2665,7 +2694,6 @@ class Server {
|
|
|
2665
2694
|
}
|
|
2666
2695
|
}))
|
|
2667
2696
|
this.app.get("/api/*", ex(async (req, res) => {
|
|
2668
|
-
console.log("req.params", req.params)
|
|
2669
2697
|
let pathComponents = req.params[0].split("/")
|
|
2670
2698
|
if (req.query && 'fs' in req.query) {
|
|
2671
2699
|
// open in file system
|
|
@@ -2689,7 +2717,6 @@ class Server {
|
|
|
2689
2717
|
try {
|
|
2690
2718
|
await this.render(req, res, pathComponents)
|
|
2691
2719
|
} catch (e) {
|
|
2692
|
-
console.log("ERROR", e)
|
|
2693
2720
|
res.status(404).send(e.message)
|
|
2694
2721
|
}
|
|
2695
2722
|
}
|
|
@@ -0,0 +1,1083 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<title>Pinokio</title>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
|
6
|
+
<link href="/xterm.min.css" rel="stylesheet" />
|
|
7
|
+
<link href="/css/fontawesome.min.css" rel="stylesheet">
|
|
8
|
+
<link href="/css/solid.min.css" rel="stylesheet">
|
|
9
|
+
<link href="/css/regular.min.css" rel="stylesheet">
|
|
10
|
+
<link href="/css/brands.min.css" rel="stylesheet">
|
|
11
|
+
<link href="/markdown.css" rel="stylesheet"/>
|
|
12
|
+
<link href="/noty.css" rel="stylesheet"/>
|
|
13
|
+
<link href="/style.css" rel="stylesheet"/>
|
|
14
|
+
<% if (agent === "electron") { %>
|
|
15
|
+
<link href="/electron.css" rel="stylesheet"/>
|
|
16
|
+
<% } %>
|
|
17
|
+
<style>
|
|
18
|
+
.line2 {
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
background: rgba(0,0,100,0.04);
|
|
23
|
+
}
|
|
24
|
+
.line2 a {
|
|
25
|
+
text-decoration: none;
|
|
26
|
+
color: black;
|
|
27
|
+
}
|
|
28
|
+
.status {
|
|
29
|
+
padding: 10px;
|
|
30
|
+
margin: 10px;
|
|
31
|
+
border-radius: 10px;
|
|
32
|
+
}
|
|
33
|
+
.status.offline {
|
|
34
|
+
background: silver;
|
|
35
|
+
}
|
|
36
|
+
.status.online {
|
|
37
|
+
background: yellowgreen;
|
|
38
|
+
}
|
|
39
|
+
.switch {
|
|
40
|
+
padding: 10px;
|
|
41
|
+
margin: 10px 0;
|
|
42
|
+
}
|
|
43
|
+
.switch[data-online=true] {
|
|
44
|
+
color: yellowgreen;
|
|
45
|
+
}
|
|
46
|
+
.button {
|
|
47
|
+
padding: 10px;
|
|
48
|
+
}
|
|
49
|
+
.on, .off {
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
}
|
|
53
|
+
header .runner {
|
|
54
|
+
padding: 10px 0 0;
|
|
55
|
+
}
|
|
56
|
+
.proxy {
|
|
57
|
+
padding: 0 10px;
|
|
58
|
+
text-align: right;
|
|
59
|
+
}
|
|
60
|
+
.proxy a {
|
|
61
|
+
text-decoration: none;
|
|
62
|
+
display: inline-block;
|
|
63
|
+
padding: 5px 10px;
|
|
64
|
+
border-radius: 2px;
|
|
65
|
+
background: black;
|
|
66
|
+
color: white;
|
|
67
|
+
}
|
|
68
|
+
.browser-options-btns {
|
|
69
|
+
display: flex;
|
|
70
|
+
padding-top: 5px;
|
|
71
|
+
}
|
|
72
|
+
.browser-options-row {
|
|
73
|
+
/*
|
|
74
|
+
border-top: 1px solid rgba(0,0,0,0.1);
|
|
75
|
+
border-bottom: 1px solid rgba(0,0,0,0.1);
|
|
76
|
+
*/
|
|
77
|
+
display: flex;
|
|
78
|
+
padding: 10px;
|
|
79
|
+
align-items: flex-start;
|
|
80
|
+
}
|
|
81
|
+
.browser-options-row h3 {
|
|
82
|
+
margin: 0;
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
margin-bottom: 3px;
|
|
85
|
+
}
|
|
86
|
+
.browser-options-row .btn.disabled {
|
|
87
|
+
opacity: 0.7;
|
|
88
|
+
}
|
|
89
|
+
.browser-options-row .btn {
|
|
90
|
+
font-weight: bold;
|
|
91
|
+
width: 100px;
|
|
92
|
+
text-align: center;
|
|
93
|
+
display: block;
|
|
94
|
+
margin-right: 10px;
|
|
95
|
+
flex-shrink: 0;
|
|
96
|
+
padding: 5px;
|
|
97
|
+
}
|
|
98
|
+
.badge {
|
|
99
|
+
font-size: 12px;
|
|
100
|
+
padding: 5px 10px;
|
|
101
|
+
background: rgba(0,0,100,0.1);
|
|
102
|
+
border-radius: 5px;
|
|
103
|
+
display: inline-block;
|
|
104
|
+
margin-top: 5px;
|
|
105
|
+
}
|
|
106
|
+
a.badge {
|
|
107
|
+
color: royalblue;
|
|
108
|
+
text-decoration: none;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
}
|
|
111
|
+
.badge a {
|
|
112
|
+
color: royalblue;
|
|
113
|
+
text-decoration: none;
|
|
114
|
+
}
|
|
115
|
+
body.dark .btn {
|
|
116
|
+
color: white;
|
|
117
|
+
border: 1px solid rgba(255,255,255,0.3);
|
|
118
|
+
}
|
|
119
|
+
body.dark .badge {
|
|
120
|
+
background: rgba(255,255,255,0.1);
|
|
121
|
+
}
|
|
122
|
+
/*
|
|
123
|
+
body.dark .browser-options-row {
|
|
124
|
+
border-top: 1px solid rgba(255,255,255,0.05);
|
|
125
|
+
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
126
|
+
}
|
|
127
|
+
*/
|
|
128
|
+
@media only screen and (max-width: 480px) {
|
|
129
|
+
.btn2 {
|
|
130
|
+
padding: 5px;
|
|
131
|
+
font-size: 11px;
|
|
132
|
+
}
|
|
133
|
+
.nav-btns {
|
|
134
|
+
flex-grow: 1;
|
|
135
|
+
justify-content: center;
|
|
136
|
+
padding: 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
</style>
|
|
140
|
+
<script src="/hotkeys.min.js"></script>
|
|
141
|
+
<script src="/sweetalert2.js"></script>
|
|
142
|
+
<script src="/noty.js"></script>
|
|
143
|
+
<script src="/notyq.js"></script>
|
|
144
|
+
<script src="/xterm.js"></script>
|
|
145
|
+
<script src="/xterm-addon-fit.js"></script>
|
|
146
|
+
<script src="/xterm-addon-web-links.js"></script>
|
|
147
|
+
<script src="/xterm-theme.js"></script>
|
|
148
|
+
<script src="/Socket.js"></script>
|
|
149
|
+
<script src="/install.js"></script>
|
|
150
|
+
<script src="/common.js"></script>
|
|
151
|
+
<script src="/opener.js"></script>
|
|
152
|
+
<script src="/nav.js"></script>
|
|
153
|
+
<script src="/fuse.js"></script>
|
|
154
|
+
<script src="/report.js"></script>
|
|
155
|
+
</head>
|
|
156
|
+
<body class='<%=theme%>'>
|
|
157
|
+
<% if (error) { %>
|
|
158
|
+
<nav class='error-message'>
|
|
159
|
+
<div><%=error%></div>
|
|
160
|
+
<div class='flexible'></div>
|
|
161
|
+
<a class='btn' target="_blank" href="https://program.pinokio.computer/#/?id=install">Download</a>
|
|
162
|
+
</nav>
|
|
163
|
+
<% } %>
|
|
164
|
+
<!--
|
|
165
|
+
<header class='grabbable'>
|
|
166
|
+
-->
|
|
167
|
+
<header class='navheader grabbable'>
|
|
168
|
+
<h1>
|
|
169
|
+
<% if (ishome) { %>
|
|
170
|
+
<a class='home' href="/"><i class="fa-solid fa-house"></i></a>
|
|
171
|
+
<button class='btn2' id='back'><i class="fa-solid fa-chevron-left"></i></button>
|
|
172
|
+
<button class='btn2' id='forward'><i class="fa-solid fa-chevron-right"></i></button>
|
|
173
|
+
<% } %>
|
|
174
|
+
<% paths.forEach((path) => { %>
|
|
175
|
+
<% if (path.action) { %>
|
|
176
|
+
<a class='path nav-button' id="<%=path.id%>" onclick="<%=path.action%>"><%-path.name%></a>
|
|
177
|
+
<% } else if (path.path) { %>
|
|
178
|
+
<a class='path' href="<%=path.path%>"><%-path.name%></a>
|
|
179
|
+
<% } %>
|
|
180
|
+
<% }) %>
|
|
181
|
+
<form class='search'>
|
|
182
|
+
<% if (display.includes("form")) { %>
|
|
183
|
+
<input type='search' class="flexible" placeholder='Filter downloaded apps'>
|
|
184
|
+
<% } else { %>
|
|
185
|
+
<% } %>
|
|
186
|
+
</form>
|
|
187
|
+
<% if (ishome) { %>
|
|
188
|
+
<div class='nav-btns'>
|
|
189
|
+
<a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|
|
190
|
+
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
191
|
+
<% if (agent === "electron") { %>
|
|
192
|
+
<a class='btn2' data-filepath="<%=filepath%>"><div><i class="fa-regular fa-folder-open"></i></div><div>Files</div></a>
|
|
193
|
+
<% } %>
|
|
194
|
+
<button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Debug</div></button>
|
|
195
|
+
<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>
|
|
196
|
+
<a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
|
|
197
|
+
<button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
|
|
198
|
+
</div>
|
|
199
|
+
<% } %>
|
|
200
|
+
</h1>
|
|
201
|
+
<% if (!ishome) { %>
|
|
202
|
+
<div class='runner'>
|
|
203
|
+
<button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> View Folder</button>
|
|
204
|
+
</div>
|
|
205
|
+
<% } %>
|
|
206
|
+
<% if (display.includes("dependencies")) { %>
|
|
207
|
+
<div class='dependencies'>
|
|
208
|
+
<h2>Prerequisites</h2>
|
|
209
|
+
<div class='item'>Download and install the following dependencies first</div>
|
|
210
|
+
<div class='requirements'>
|
|
211
|
+
<% config.dependencies.forEach((dep) => { %>
|
|
212
|
+
<% if (dep.downloaded) { %>
|
|
213
|
+
<div class='item'><i class="fa-solid fa-check"></i> <a class='downloaded' href="<%=dep.downloaded%>" target="_blank"><%=dep.uri%></a><div class='flexible'></div></div>
|
|
214
|
+
<% } else { %>
|
|
215
|
+
<div class='item'><a class='btn' href="/?mode=download&uri=<%=dep.uri%>" target="_blank"><i class="fa-solid fa-download"></i> Download</a> <%=dep.uri%><div class='flexible'></div></div>
|
|
216
|
+
<% } %>
|
|
217
|
+
<% }) %>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
<% } %>
|
|
221
|
+
</header>
|
|
222
|
+
<main>
|
|
223
|
+
<div id='terminal' class='hidden'></div>
|
|
224
|
+
<div class='container'>
|
|
225
|
+
<% if (ishome) { %>
|
|
226
|
+
<% if (running.length === 0 && notRunning.length === 0) { %>
|
|
227
|
+
<% } else { %>
|
|
228
|
+
<div class='browser-options'>
|
|
229
|
+
<% if (agent === "electron") { %>
|
|
230
|
+
<div class='browser-options-row'>
|
|
231
|
+
<% if (agent === "electron") { %>
|
|
232
|
+
<a href="/" target="_blank" class='btn' features="browser"><div><i class="fa-solid fa-square-up-right"></i> Open</div></a>
|
|
233
|
+
<% } else { %>
|
|
234
|
+
<a href="/" target="_blank" class='btn'><div><i class="fa-solid fa-square-up-right"></i> Open</div></a>
|
|
235
|
+
<% } %>
|
|
236
|
+
<div class='flexible'>
|
|
237
|
+
<h3><i class="fa-solid fa-bolt"></i> Instant Launch</h3>
|
|
238
|
+
<div>(Experimental) Directly open pinokio apps from your favorite browser address bar at localhost. If an app you're trying to use is already running, it will instantly load. If it's not, the app will first launch and then load the website.</div>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
<% } %>
|
|
242
|
+
<div class='browser-options-row'>
|
|
243
|
+
<a href="/proxy" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
|
|
244
|
+
<div class='flexible'>
|
|
245
|
+
<h3><i class="fa-solid fa-wifi"></i> Local Sharing</h3>
|
|
246
|
+
<div>Serve Pinokio, installed apps, and even external apps (example: Ollama) to any device on the same network.</div>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
<!--
|
|
250
|
+
<div class='browser-options-row'>
|
|
251
|
+
<a href="/proxy" class='flexible'>
|
|
252
|
+
<h3><i class="fa-solid fa-wifi"></i> Local Share</h3>
|
|
253
|
+
<div>Access Pinokio, Ollama, and other 3rd party apps from any device on the same network. By default it's off.</div>
|
|
254
|
+
</a>
|
|
255
|
+
<% if (false) { %>
|
|
256
|
+
<% if (proxy) { %>
|
|
257
|
+
<a id='wifi-stop' data-proxy="<%=proxy.proxy%>" class='btn'><div><i class="fa-solid fa-stop"></i> Stop</div></a>
|
|
258
|
+
<div class='flexible'>
|
|
259
|
+
<h3><i class="fa-solid fa-wifi"></i> Local Share</h3>
|
|
260
|
+
<div>Access Pinokio from any device on the same network. By default it's off.</div>
|
|
261
|
+
<span class='badge'><i class="fa-solid fa-circle-notch fa-spin"></i> Running at <a href="<%=proxy.proxy%>" target="_blank" features="browser"><%=proxy.proxy%></a></span>
|
|
262
|
+
<a id='wifi-qr' class='badge'><i class="fa-solid fa-qrcode"></i> Scan QR Code</a>
|
|
263
|
+
</div>
|
|
264
|
+
<% } else { %>
|
|
265
|
+
<a id='wifi' class='btn'><div><i class="fa-solid fa-play"></i> Start</div></a>
|
|
266
|
+
<a id='wifi-starting' class='btn disabled hidden'><div><i class="fa-solid fa-circle-notch fa-spin"></i> Starting</div></a>
|
|
267
|
+
<div class='flexible'>
|
|
268
|
+
<h3><i class="fa-solid fa-wifi"></i> Local Share</h3>
|
|
269
|
+
<div>Access Pinokio from any device on the same network. By default it's off.</div>
|
|
270
|
+
</div>
|
|
271
|
+
<% } %>
|
|
272
|
+
<% } %>
|
|
273
|
+
</div>
|
|
274
|
+
-->
|
|
275
|
+
<div class='browser-options-row hidden'>
|
|
276
|
+
<% if (cloudflare_pub) { %>
|
|
277
|
+
<a id='cloudflare-stop' class='btn'><div><i class="fa-solid fa-stop"></i> Stop</div></a>
|
|
278
|
+
<div class='flexible'>
|
|
279
|
+
<h3>Public Share</h3>
|
|
280
|
+
<div>Open up your Pinokio server to the open internet (anyone with the URL can access)</div>
|
|
281
|
+
<span class='badge'><i class="fa-solid fa-circle-notch fa-spin"></i> Running at <a href="<%=cloudflare_pub%>" target="_blank" features="browser"><%=cloudflare_pub%></a></span>
|
|
282
|
+
<a id='cloudflare-qr' class='badge'><i class="fa-solid fa-qrcode"></i> Scan QR Code</a>
|
|
283
|
+
</div>
|
|
284
|
+
<% } else { %>
|
|
285
|
+
<a id='cloudflare' class='btn'><div><i class="fa-solid fa-play"></i> Start</div></a>
|
|
286
|
+
<a id='cloudflare-starting' class='btn disabled hidden'><div><i class="fa-solid fa-circle-notch fa-spin"></i> Starting</div></a>
|
|
287
|
+
<div class='flexible'>
|
|
288
|
+
<h3>Public Share</h3>
|
|
289
|
+
<div>Open up your Pinokio server to the open internet (anyone with the URL can access)</div>
|
|
290
|
+
</div>
|
|
291
|
+
<% } %>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
<% } %>
|
|
295
|
+
<!--
|
|
296
|
+
<div class='type-tabs'>
|
|
297
|
+
<% if (mode === "task") { %>
|
|
298
|
+
<a class='type-tab' href="/"><img src='/pinokio-<%=theme=='dark' ? 'white' : 'black'%>.png'> Apps</a>
|
|
299
|
+
<a class='type-tab selected' href="/?mode=task"> <img src='/<%=theme=='dark' ? 'term-dark.png' : 'term-white.png'%>'> Tasks</a>
|
|
300
|
+
<% } else { %>
|
|
301
|
+
<a class='type-tab selected' href="/"><img src='/pinokio-<%=theme=='dark' ? 'white' : 'black'%>.png'> Apps</a>
|
|
302
|
+
<a class='type-tab' href="/?mode=task"> <img src='/<%=theme=='dark' ? 'term-dark.png' : 'term-white.png'%>'> Tasks</a>
|
|
303
|
+
<% } %>
|
|
304
|
+
</div>
|
|
305
|
+
-->
|
|
306
|
+
<% if (running.length > 0) { %>
|
|
307
|
+
<div class='running-apps'>
|
|
308
|
+
<div class='header-label'>Running</div>
|
|
309
|
+
<% running.forEach((item) => { %>
|
|
310
|
+
<a href="<%=item.browser_url%>" data-description="<%=item.description%>" data-index="<%=item.index%>" data-name="<%=item.name%>" data-uri="<%=item.uri%>" class='line align-top'>
|
|
311
|
+
<h3>
|
|
312
|
+
<% if (item.icon) { %>
|
|
313
|
+
<img src="<%=item.icon%>">
|
|
314
|
+
<% } else { %>
|
|
315
|
+
<% if (theme === 'dark') { %>
|
|
316
|
+
<img src="/pinokio-white.png">
|
|
317
|
+
<% } else { %>
|
|
318
|
+
<img src="/pinokio-black.png">
|
|
319
|
+
<% } %>
|
|
320
|
+
<!--
|
|
321
|
+
<div class='avatar'>
|
|
322
|
+
<i class="fa-regular fa-circle-dot"></i>
|
|
323
|
+
</div>
|
|
324
|
+
-->
|
|
325
|
+
<% } %>
|
|
326
|
+
<div class='col'>
|
|
327
|
+
<div class='uri'><i class="fa-regular fa-folder"></i><%=item.url%></div>
|
|
328
|
+
<div class='title'><%=item.name%></div>
|
|
329
|
+
<div class='description'><%=item.description%></div>
|
|
330
|
+
<div>
|
|
331
|
+
<button class='btn browse' data-src="<%=item.browser_url%>/browse">
|
|
332
|
+
<i class='fa-regular fa-folder-open'></i>
|
|
333
|
+
</button>
|
|
334
|
+
<button class='btn del' data-src="<%=item.url%>">
|
|
335
|
+
<i class="fa-solid fa-trash-can"></i>
|
|
336
|
+
</button>
|
|
337
|
+
<% if (item.running_scripts) { %>
|
|
338
|
+
<% item.running_scripts.forEach((s) => { %>
|
|
339
|
+
<button class='btn shutdown' data-src="<%=s.path%>">
|
|
340
|
+
<i class="fa-solid fa-stop"></i> Stop <%=s.name%>
|
|
341
|
+
<i class='fa-solid fa-spin fa-circle-notch'></i>
|
|
342
|
+
</button>
|
|
343
|
+
<% }) %>
|
|
344
|
+
<% } %>
|
|
345
|
+
</div>
|
|
346
|
+
<% if (item.shortcuts && item.shortcuts.length > 0) { %>
|
|
347
|
+
<div class='btns'>
|
|
348
|
+
<% item.shortcuts.forEach((btn) => { %>
|
|
349
|
+
<% if (btn.btn) { %>
|
|
350
|
+
<button data-action="<%=btn.action ? JSON.stringify(btn.action) : ''%>" class='btn menu-btn'><%-btn.btn%></button>
|
|
351
|
+
<% } %>
|
|
352
|
+
<% }) %>
|
|
353
|
+
</div>
|
|
354
|
+
<% } %>
|
|
355
|
+
</div>
|
|
356
|
+
<div class='spinner'>
|
|
357
|
+
<i class="fa-solid fa-chevron-right"></i>
|
|
358
|
+
<!--
|
|
359
|
+
<i class="fa-solid fa-circle-notch fa-spin"></i>
|
|
360
|
+
-->
|
|
361
|
+
</div>
|
|
362
|
+
</h3>
|
|
363
|
+
</a>
|
|
364
|
+
<% }) %>
|
|
365
|
+
</div>
|
|
366
|
+
<% } %>
|
|
367
|
+
<% if (notRunning.length > 0) { %>
|
|
368
|
+
<div class='not-running-apps'>
|
|
369
|
+
<div class='header-label'>Not Running</div>
|
|
370
|
+
<% notRunning.forEach((item) => { %>
|
|
371
|
+
<a href="<%=item.browser_url%>" data-description="<%=item.description%>" data-index="<%=item.index%>" data-name="<%=item.name%>" data-uri="<%=item.uri%>" class='line align-top'>
|
|
372
|
+
<h3>
|
|
373
|
+
<% if (item.icon) { %>
|
|
374
|
+
<img src="<%=item.icon%>">
|
|
375
|
+
<% } else { %>
|
|
376
|
+
<!--
|
|
377
|
+
<div class='avatar'>
|
|
378
|
+
<i class="fa-regular fa-circle-dot"></i>
|
|
379
|
+
</div>
|
|
380
|
+
-->
|
|
381
|
+
<% if (theme === 'dark') { %>
|
|
382
|
+
<img src="/pinokio-white.png">
|
|
383
|
+
<% } else { %>
|
|
384
|
+
<img src="/pinokio-black.png">
|
|
385
|
+
<% } %>
|
|
386
|
+
<% } %>
|
|
387
|
+
<div class='col'>
|
|
388
|
+
<div class='uri'><i class="fa-regular fa-folder"></i><%=item.url%></div>
|
|
389
|
+
<div class='title'><%=item.name%></div>
|
|
390
|
+
<div class='description'><%=item.description%></div>
|
|
391
|
+
<button class='btn browse' data-src="<%=item.browser_url%>/browse">
|
|
392
|
+
<i class='fa-regular fa-folder-open'></i>
|
|
393
|
+
</button>
|
|
394
|
+
<button class='btn del' data-src="<%=item.url%>">
|
|
395
|
+
<i class="fa-solid fa-trash-can"></i>
|
|
396
|
+
</button>
|
|
397
|
+
<% if (item.shortcuts && item.shortcuts.length > 0) { %>
|
|
398
|
+
<div class='btns'>
|
|
399
|
+
<% item.shortcuts.forEach((btn) => { %>
|
|
400
|
+
<% if (btn.btn) { %>
|
|
401
|
+
<button data-action="<%=btn.action ? JSON.stringify(btn.action) : ''%>" class='btn menu-btn'><%-btn.btn%></button>
|
|
402
|
+
<% } %>
|
|
403
|
+
<% }) %>
|
|
404
|
+
</div>
|
|
405
|
+
<% } %>
|
|
406
|
+
</div>
|
|
407
|
+
<div class='spinner'>
|
|
408
|
+
<i class="fa-solid fa-chevron-right"></i>
|
|
409
|
+
</div>
|
|
410
|
+
</h3>
|
|
411
|
+
</a>
|
|
412
|
+
<% }) %>
|
|
413
|
+
</div>
|
|
414
|
+
<% } %>
|
|
415
|
+
<% if (running.length === 0 && notRunning.length === 0) { %>
|
|
416
|
+
<div class='placeholder'>
|
|
417
|
+
<h1>Welcome.</h1>
|
|
418
|
+
<br>
|
|
419
|
+
<div>Get started by installing some Pinokio scripts.</div>
|
|
420
|
+
<a href="/?mode=explore" class='btn'><i class="fa-solid fa-globe"></i> Visit Discover Page</a>
|
|
421
|
+
</div>
|
|
422
|
+
<% } %>
|
|
423
|
+
<% } else { %>
|
|
424
|
+
<% items.forEach((item, index) => { %>
|
|
425
|
+
<a data-description="<%=item.description%>" data-index="<%=index%>" data-name="<%=item.name%>" data-uri="<%=item.uri%>" class='line thick' href="<%=item.url%>">
|
|
426
|
+
<h3>
|
|
427
|
+
<% if (item.icon) { %>
|
|
428
|
+
<i class="<%=item.icon%>"></i>
|
|
429
|
+
<% } else { %>
|
|
430
|
+
<i class="fa-regular fa-folder"></i>
|
|
431
|
+
<% } %>
|
|
432
|
+
<%=item.name%>
|
|
433
|
+
</h3>
|
|
434
|
+
<div class='description'><%=item.description%></div>
|
|
435
|
+
</a>
|
|
436
|
+
<% }) %>
|
|
437
|
+
<% } %>
|
|
438
|
+
<% if (readme) { %>
|
|
439
|
+
<div class='readme markdown-body'>
|
|
440
|
+
<div class='content'><%-readme%></div>
|
|
441
|
+
</div>
|
|
442
|
+
<% } %>
|
|
443
|
+
<% if (display.includes("onboarding")) { %>
|
|
444
|
+
<!--
|
|
445
|
+
<div class='container'>
|
|
446
|
+
<div class='content'>
|
|
447
|
+
<h2>Quickstart</h2>
|
|
448
|
+
<div>Install llama</div>
|
|
449
|
+
<br>
|
|
450
|
+
<button class='btn' id='llama'>Install</button>
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
-->
|
|
454
|
+
<% } %>
|
|
455
|
+
</div>
|
|
456
|
+
</main>
|
|
457
|
+
<script>
|
|
458
|
+
let paths = location.pathname.split("/").filter(x=>x)
|
|
459
|
+
var term
|
|
460
|
+
const n = new N()
|
|
461
|
+
let socket = new Socket()
|
|
462
|
+
const pull = async () => {
|
|
463
|
+
if (!term) term = createTerm()
|
|
464
|
+
socket.close()
|
|
465
|
+
await new Promise((resolve, reject) => {
|
|
466
|
+
let cwd
|
|
467
|
+
let chunks = location.pathname.split("/").filter((x) => { return x })
|
|
468
|
+
if (chunks.length > 0) {
|
|
469
|
+
//cwd = chunks.slice(1).join("/")
|
|
470
|
+
cwd = "~/" + chunks.join("/")
|
|
471
|
+
} else {
|
|
472
|
+
cwd = "."
|
|
473
|
+
}
|
|
474
|
+
socket.run({
|
|
475
|
+
method: "shell.run",
|
|
476
|
+
params: {
|
|
477
|
+
message: `git pull`,
|
|
478
|
+
// path: "<%=uri%>",//cwd
|
|
479
|
+
path: cwd
|
|
480
|
+
}
|
|
481
|
+
}, (packet) => {
|
|
482
|
+
if (packet.type === 'stream') {
|
|
483
|
+
term.write(packet.data.raw)
|
|
484
|
+
} else if (packet.type === "result") {
|
|
485
|
+
resolve()
|
|
486
|
+
} else if (packet.type === "error") {
|
|
487
|
+
n.Noty({
|
|
488
|
+
text: packet.data
|
|
489
|
+
})
|
|
490
|
+
}
|
|
491
|
+
})
|
|
492
|
+
})
|
|
493
|
+
<% if (config && config.update) { %>
|
|
494
|
+
n.Noty({
|
|
495
|
+
text: "Success! An update script exists. Click to visit and run the update script!",
|
|
496
|
+
type: "success",
|
|
497
|
+
callbacks: {
|
|
498
|
+
onClose: () => {
|
|
499
|
+
location.href = "<%=config.update%>"
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
})
|
|
503
|
+
<% } else { %>
|
|
504
|
+
n.Noty({
|
|
505
|
+
text: "Success! Click to refresh.",
|
|
506
|
+
type: "success",
|
|
507
|
+
callbacks: {
|
|
508
|
+
onClose: () => {
|
|
509
|
+
location.href = location.href
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
})
|
|
513
|
+
<% } %>
|
|
514
|
+
}
|
|
515
|
+
<% if (display.includes("onboarding")) { %>
|
|
516
|
+
//document.querySelector("#llama").addEventListener("click", async (e) => {
|
|
517
|
+
// if (!term) term = createTerm()
|
|
518
|
+
// await install("llama", "https://github.com/malfunctionize/lla", term, socket)
|
|
519
|
+
//})
|
|
520
|
+
<% } %>
|
|
521
|
+
<% if (display.includes("form")) { %>
|
|
522
|
+
let list = []
|
|
523
|
+
document.querySelectorAll(".line").forEach((el, index) => {
|
|
524
|
+
list.push({
|
|
525
|
+
index: parseInt(el.getAttribute("data-index")),
|
|
526
|
+
name: el.getAttribute("data-name"),
|
|
527
|
+
description: el.getAttribute("data-description"),
|
|
528
|
+
uri: el.getAttribute("data-uri")
|
|
529
|
+
})
|
|
530
|
+
})
|
|
531
|
+
const search = (items, value) => {
|
|
532
|
+
let filtered = []
|
|
533
|
+
for(let i=0; i<items.length; i++) {
|
|
534
|
+
let item = items[i]
|
|
535
|
+
let re = new RegExp(value, "i")
|
|
536
|
+
if (re.test(item.name)) {
|
|
537
|
+
filtered.push({ item })
|
|
538
|
+
} else if (re.test(item.description)) {
|
|
539
|
+
filtered.push({ item })
|
|
540
|
+
} else if (re.test(item.uri)) {
|
|
541
|
+
filtered.push({ item })
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return filtered
|
|
545
|
+
}
|
|
546
|
+
//const fuse = new Fuse(list, {
|
|
547
|
+
// threshold: 0.3,
|
|
548
|
+
// keys: [{
|
|
549
|
+
// name: "name",
|
|
550
|
+
// weight: 5,
|
|
551
|
+
// }, {
|
|
552
|
+
// name: "description",
|
|
553
|
+
// weight: 1,
|
|
554
|
+
// }],
|
|
555
|
+
// includeScore: true,
|
|
556
|
+
// includeMatches: true
|
|
557
|
+
//})
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
let selectedIndex = -1
|
|
561
|
+
let selectedBtnIndex = 0
|
|
562
|
+
let filteredCount = list.length
|
|
563
|
+
let filteredBtnsCount = 0
|
|
564
|
+
|
|
565
|
+
const renderSearch = () => {
|
|
566
|
+
let target = document.querySelector("form input[type=search]")
|
|
567
|
+
let result
|
|
568
|
+
if (target.value.trim().length === 0) {
|
|
569
|
+
result = list.map((i, index) => {
|
|
570
|
+
return { item: i }
|
|
571
|
+
})
|
|
572
|
+
} else {
|
|
573
|
+
result = search(list, target.value)
|
|
574
|
+
}
|
|
575
|
+
let all = document.querySelectorAll(".line")
|
|
576
|
+
for(let el of all) {
|
|
577
|
+
el.classList.add("hidden")
|
|
578
|
+
el.classList.remove("selected")
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
filteredCount = result.length
|
|
582
|
+
for(let i=0; i<result.length; i++) {
|
|
583
|
+
let selector = result[i]
|
|
584
|
+
//let el = document.querySelector(".line[data-name='" + selector.item.name + "']")
|
|
585
|
+
let el = document.querySelector(".line[data-index='" + selector.item.index + "']")
|
|
586
|
+
el.classList.remove("hidden")
|
|
587
|
+
if (i === selectedIndex) {
|
|
588
|
+
el.classList.add("selected")
|
|
589
|
+
let btns = el.querySelectorAll(".btns a")
|
|
590
|
+
filteredBtnsCount = btns.length
|
|
591
|
+
btns.forEach((_el, j) => {
|
|
592
|
+
if (selectedBtnIndex === j) {
|
|
593
|
+
_el.classList.add("selected")
|
|
594
|
+
} else {
|
|
595
|
+
_el.classList.remove("selected")
|
|
596
|
+
}
|
|
597
|
+
})
|
|
598
|
+
} else {
|
|
599
|
+
el.classList.remove("selected")
|
|
600
|
+
let btns = el.querySelectorAll(".btns a")
|
|
601
|
+
btns.forEach((_el, j) => {
|
|
602
|
+
_el.classList.remove("selected")
|
|
603
|
+
})
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
renderSearch()
|
|
610
|
+
|
|
611
|
+
document.querySelector("form input[type=search]").addEventListener("input", (e) => {
|
|
612
|
+
selectedIndex = 0
|
|
613
|
+
selectedBtnIndex = 0
|
|
614
|
+
renderSearch()
|
|
615
|
+
/*
|
|
616
|
+
if (e.target.value.trim().length === 0) {
|
|
617
|
+
let all = document.querySelectorAll(".line")
|
|
618
|
+
for(let el of all) {
|
|
619
|
+
el.classList.remove("hidden")
|
|
620
|
+
}
|
|
621
|
+
} else {
|
|
622
|
+
let all = document.querySelectorAll(".line")
|
|
623
|
+
for(let el of all) {
|
|
624
|
+
el.classList.add("hidden")
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
//let result = fuse.search(e.target.value)
|
|
628
|
+
let result = search(list, e.target.value)
|
|
629
|
+
// result.sort((x, y) => {
|
|
630
|
+
// return y.score - x.score
|
|
631
|
+
// })
|
|
632
|
+
let i = 0
|
|
633
|
+
//for(let selector of result) {
|
|
634
|
+
for(let i=0; i<result.length; i++) {
|
|
635
|
+
let selector = result[i]
|
|
636
|
+
let el = document.querySelector(".line[data-name='" + selector.item.name + "']")
|
|
637
|
+
el.classList.remove("hidden")
|
|
638
|
+
if (i === 0) {
|
|
639
|
+
el.classList.add("selected")
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
*/
|
|
644
|
+
})
|
|
645
|
+
document.querySelector("form input[type=search]").focus()
|
|
646
|
+
<% } %>
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
// if (el) {
|
|
650
|
+
// let url = el.getAttribute("data-url")
|
|
651
|
+
// if (url) {
|
|
652
|
+
// let target = el.getAttribute("data-target")
|
|
653
|
+
// if (target && target.length > 0) {
|
|
654
|
+
// let agent = el.getAttribute("data-agent")
|
|
655
|
+
// if (agent && agent.length > 0) {
|
|
656
|
+
// window.open(url, target, agent)
|
|
657
|
+
// } else {
|
|
658
|
+
// window.open(url, target)
|
|
659
|
+
// }
|
|
660
|
+
// } else {
|
|
661
|
+
// location.href = url
|
|
662
|
+
// }
|
|
663
|
+
// }
|
|
664
|
+
// }
|
|
665
|
+
//document.querySelector(".runner").addEventListener("click", async (e) => {
|
|
666
|
+
// let el = e.target.closest(".btn")
|
|
667
|
+
// if (!el) {
|
|
668
|
+
// if (el.classList.contains("btn")) {
|
|
669
|
+
// el = e.target
|
|
670
|
+
// }
|
|
671
|
+
// }
|
|
672
|
+
//
|
|
673
|
+
// if (el) {
|
|
674
|
+
// let url = el.getAttribute("data-url")
|
|
675
|
+
// if (url) {
|
|
676
|
+
// let target = el.getAttribute("data-target")
|
|
677
|
+
// if (target && target.length > 0) {
|
|
678
|
+
// let agent = el.getAttribute("data-agent")
|
|
679
|
+
// if (agent && agent.length > 0) {
|
|
680
|
+
// window.open(url, target, agent)
|
|
681
|
+
// } else {
|
|
682
|
+
// window.open(url, target)
|
|
683
|
+
// }
|
|
684
|
+
// } else {
|
|
685
|
+
// location.href = url
|
|
686
|
+
// }
|
|
687
|
+
// }
|
|
688
|
+
// }
|
|
689
|
+
//})
|
|
690
|
+
<% if (display.includes("install")) { %>
|
|
691
|
+
document.querySelector("#install").addEventListener("click", async (e) => {
|
|
692
|
+
location.href = e.target.getAttribute("data-url")
|
|
693
|
+
})
|
|
694
|
+
<% } %>
|
|
695
|
+
<% if (display.includes("explore")) { %>
|
|
696
|
+
document.querySelector("#explore").addEventListener("click", async (e) => {
|
|
697
|
+
e.preventDefault()
|
|
698
|
+
e.stopPropagation()
|
|
699
|
+
location.href = "/?mode=explore"
|
|
700
|
+
})
|
|
701
|
+
<% } %>
|
|
702
|
+
//Reporter()
|
|
703
|
+
/*
|
|
704
|
+
<% if (display.includes("dependencies")) { %>
|
|
705
|
+
document.querySelector(".requirements").addEventListener("click", (e) => {
|
|
706
|
+
e.preventDefault()
|
|
707
|
+
e.stopPropagation()
|
|
708
|
+
let el = e.target.closest(".opener")
|
|
709
|
+
if (!el) {
|
|
710
|
+
if (e.target.classList.contains("opener")) {
|
|
711
|
+
el = e.target
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
if (el) {
|
|
715
|
+
window.open(el.getAttribute("data-href"), "_blank", "app")
|
|
716
|
+
}
|
|
717
|
+
})
|
|
718
|
+
<% } %>
|
|
719
|
+
*/
|
|
720
|
+
let params = new URLSearchParams(location.search)
|
|
721
|
+
let selected = params.get("selected")
|
|
722
|
+
if (selected) {
|
|
723
|
+
document.querySelector("form input[type=search]").value = selected
|
|
724
|
+
document.querySelector("form input[type=search]").dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
|
|
725
|
+
}
|
|
726
|
+
if (document.querySelector("form input[type=search]")) {
|
|
727
|
+
document.querySelector("form input[type=search]").addEventListener("input", (e) => {
|
|
728
|
+
let p
|
|
729
|
+
if (e.target.value && e.target.value.trim().length > 0) {
|
|
730
|
+
p = location.pathname + "?selected=" + e.target.value
|
|
731
|
+
} else {
|
|
732
|
+
p = location.pathname
|
|
733
|
+
}
|
|
734
|
+
window.history.pushState({ path: p }, '', p);
|
|
735
|
+
})
|
|
736
|
+
}
|
|
737
|
+
<% if (ishome) { %>
|
|
738
|
+
document.addEventListener("keydown", (e) => {
|
|
739
|
+
e = e || window.event;
|
|
740
|
+
if (e.key === "ArrowUp") {
|
|
741
|
+
console.log("up arrow pressed");
|
|
742
|
+
selectedIndex = Math.max(selectedIndex-1, 0)
|
|
743
|
+
selectedBtnIndex = 0
|
|
744
|
+
renderSearch()
|
|
745
|
+
let selected = document.querySelector(".line.selected")
|
|
746
|
+
selected.scrollIntoView(false)
|
|
747
|
+
//
|
|
748
|
+
} else if (e.key === "ArrowDown") {
|
|
749
|
+
console.log("before selectedIndex", selectedIndex)
|
|
750
|
+
selectedIndex = Math.min(filteredCount-1, selectedIndex+1)
|
|
751
|
+
selectedBtnIndex = 0
|
|
752
|
+
console.log("after selectedIndex", selectedIndex)
|
|
753
|
+
renderSearch()
|
|
754
|
+
console.log("down arrow pressed");
|
|
755
|
+
let selected = document.querySelector(".line.selected")
|
|
756
|
+
selected.scrollIntoView(false)
|
|
757
|
+
} else if (e.key === "ArrowLeft") {
|
|
758
|
+
selectedBtnIndex = Math.max(selectedBtnIndex-1, 0)
|
|
759
|
+
console.log("left arrow pressed");
|
|
760
|
+
console.log("selectedBtnIndex", selectedBtnIndex)
|
|
761
|
+
renderSearch()
|
|
762
|
+
} else if (e.key === "ArrowRight") {
|
|
763
|
+
console.log("right arrow pressed");
|
|
764
|
+
selectedBtnIndex = Math.min(filteredBtnsCount-1, selectedBtnIndex+1)
|
|
765
|
+
console.log("selectedBtnIndex", selectedBtnIndex)
|
|
766
|
+
renderSearch()
|
|
767
|
+
} else if (e.key === "Enter") {
|
|
768
|
+
//let selected = document.querySelector(".line.selected:not(.hidden) .btns a.selected")
|
|
769
|
+
//let selected = document.querySelector(".line.selected:not(.hidden) .title a")
|
|
770
|
+
let selected = document.querySelector(".line.selected:not(.hidden)")
|
|
771
|
+
console.log("selected", selected)
|
|
772
|
+
if (selected) {
|
|
773
|
+
e.preventDefault()
|
|
774
|
+
e.stopPropagation()
|
|
775
|
+
selected.click()
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
document.addEventListener("click", async (e) => {
|
|
780
|
+
|
|
781
|
+
let target
|
|
782
|
+
|
|
783
|
+
if (e.target.classList.contains("shutdown")) {
|
|
784
|
+
target = e.target
|
|
785
|
+
} else {
|
|
786
|
+
target = e.target.closest(".shutdown")
|
|
787
|
+
}
|
|
788
|
+
if (target) {
|
|
789
|
+
e.preventDefault()
|
|
790
|
+
e.stopPropagation()
|
|
791
|
+
let src = target.getAttribute("data-src")
|
|
792
|
+
console.log("src", src)
|
|
793
|
+
|
|
794
|
+
socket.run({
|
|
795
|
+
method: "kernel.api.stop",
|
|
796
|
+
params: {
|
|
797
|
+
uri: "~/" + src
|
|
798
|
+
}
|
|
799
|
+
}, (packet) => {
|
|
800
|
+
console.log("packet", packet)
|
|
801
|
+
if (packet.type === "result") {
|
|
802
|
+
socket.close()
|
|
803
|
+
target.querySelector("i.fa-stop").className = "fa-solid fa-check"
|
|
804
|
+
target.querySelector("i.fa-spin").classList.add("hidden")
|
|
805
|
+
n.Noty({
|
|
806
|
+
text: `stopped ${src}`,
|
|
807
|
+
silent: true
|
|
808
|
+
})
|
|
809
|
+
setTimeout(() => {
|
|
810
|
+
location.href = location.href
|
|
811
|
+
}, 1000)
|
|
812
|
+
}
|
|
813
|
+
})
|
|
814
|
+
|
|
815
|
+
return
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
if (e.target.classList.contains("browse")) {
|
|
820
|
+
target = e.target
|
|
821
|
+
} else {
|
|
822
|
+
target = e.target.closest(".browse")
|
|
823
|
+
}
|
|
824
|
+
if (target) {
|
|
825
|
+
e.preventDefault()
|
|
826
|
+
e.stopPropagation()
|
|
827
|
+
let src = target.getAttribute("data-src")
|
|
828
|
+
location.href = src
|
|
829
|
+
return
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
// delete
|
|
834
|
+
if (e.target.classList.contains("del")) {
|
|
835
|
+
target = e.target
|
|
836
|
+
} else {
|
|
837
|
+
target = e.target.closest(".del")
|
|
838
|
+
}
|
|
839
|
+
if (target) {
|
|
840
|
+
e.preventDefault()
|
|
841
|
+
e.stopPropagation()
|
|
842
|
+
let confirmed = confirm("Are you sure you want to delete the folder? All files in the folder will be gone.")
|
|
843
|
+
if (confirmed) {
|
|
844
|
+
let itemEl = target.closest(".line[data-uri]")
|
|
845
|
+
let name = itemEl.getAttribute("data-uri")
|
|
846
|
+
console.log("delete", name)
|
|
847
|
+
Swal.fire({
|
|
848
|
+
html: '<i class="fa-solid fa-circle-notch fa-spin"></i> Deleting',
|
|
849
|
+
customClass: {
|
|
850
|
+
container: "loader-container",
|
|
851
|
+
popup: "loader-popup",
|
|
852
|
+
htmlContainer: "loader-dialog",
|
|
853
|
+
footer: "hidden",
|
|
854
|
+
actions: "hidden"
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
let res = await fetch("/pinokio/delete", {
|
|
858
|
+
method: "post",
|
|
859
|
+
headers: {
|
|
860
|
+
"Content-Type": "application/json"
|
|
861
|
+
},
|
|
862
|
+
body: JSON.stringify({ name })
|
|
863
|
+
}).then((res) => {
|
|
864
|
+
return res.json()
|
|
865
|
+
})
|
|
866
|
+
console.log("res", res)
|
|
867
|
+
Swal.close()
|
|
868
|
+
if (res) {
|
|
869
|
+
if (res.success) {
|
|
870
|
+
location.href = "/"
|
|
871
|
+
} else if (res.error) {
|
|
872
|
+
alert(res.error)
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
} else {
|
|
876
|
+
}
|
|
877
|
+
return
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
if (document.querySelector(".container")) {
|
|
883
|
+
document.querySelector(".container").addEventListener("click", async (e) => {
|
|
884
|
+
let el = e.target.closest(".menu-btn")
|
|
885
|
+
if (!el) {
|
|
886
|
+
if (el.classList.contains("menu-btn")) {
|
|
887
|
+
el = e.target
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
console.log("EL", el)
|
|
892
|
+
|
|
893
|
+
if (el) {
|
|
894
|
+
e.preventDefault()
|
|
895
|
+
e.stopPropagation()
|
|
896
|
+
let actionStr = el.getAttribute("data-action")
|
|
897
|
+
if (actionStr) {
|
|
898
|
+
let action = JSON.parse(actionStr)
|
|
899
|
+
console.log("action", action)
|
|
900
|
+
if (action.method === "stop" && action.uri) {
|
|
901
|
+
socket.run({
|
|
902
|
+
method: "kernel.api.stop",
|
|
903
|
+
params: {
|
|
904
|
+
uri: action.uri//"~" + location.pathname
|
|
905
|
+
}
|
|
906
|
+
}, (packet) => {
|
|
907
|
+
console.log("packet", packet)
|
|
908
|
+
if (packet.type === "result") {
|
|
909
|
+
socket.close()
|
|
910
|
+
location.href = location.href
|
|
911
|
+
}
|
|
912
|
+
})
|
|
913
|
+
return
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
}
|
|
918
|
+
})
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
/*
|
|
925
|
+
target = (e.target.classList.contains(".btn") ? e.target : e.target.closest(".btn"))
|
|
926
|
+
if (target) {
|
|
927
|
+
target.classList.add("clicked")
|
|
928
|
+
document.querySelectorAll(".line .btns .btn").forEach((e) => {
|
|
929
|
+
e.classList.remove("selected")
|
|
930
|
+
})
|
|
931
|
+
target.classList.add("selected")
|
|
932
|
+
target.closest(".line").classList.add("selected")
|
|
933
|
+
return
|
|
934
|
+
}
|
|
935
|
+
*/
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
})
|
|
939
|
+
<% if (proxy) { %>
|
|
940
|
+
if (document.querySelector("#wifi-qr")) {
|
|
941
|
+
document.querySelector("#wifi-qr").addEventListener("click", async (e) => {
|
|
942
|
+
await Swal.fire({
|
|
943
|
+
title: "Local Share",
|
|
944
|
+
customClass: {
|
|
945
|
+
popup: "min-popup",
|
|
946
|
+
title: "min-title"
|
|
947
|
+
},
|
|
948
|
+
showConfirmButton: false,
|
|
949
|
+
html: `<div class='min-modal'>
|
|
950
|
+
<div>Access Pinokio from</div>
|
|
951
|
+
<div>any local network device</div>
|
|
952
|
+
<div><img src="<%=qr%>"></div>
|
|
953
|
+
<a href="<%=proxy.proxy%>" target="_blank"><%=proxy.proxy%></a>
|
|
954
|
+
</div>`
|
|
955
|
+
})
|
|
956
|
+
})
|
|
957
|
+
}
|
|
958
|
+
if (document.querySelector("#wifi-stop")) {
|
|
959
|
+
document.querySelector("#wifi-stop").addEventListener("click", async (e) => {
|
|
960
|
+
let res = await fetch("/unpublish", {
|
|
961
|
+
method: "post",
|
|
962
|
+
headers: {
|
|
963
|
+
"Content-Type": "application/json"
|
|
964
|
+
},
|
|
965
|
+
body: JSON.stringify({
|
|
966
|
+
type: "local"
|
|
967
|
+
})
|
|
968
|
+
}).then((res) => {
|
|
969
|
+
return res.json()
|
|
970
|
+
})
|
|
971
|
+
console.log(res)
|
|
972
|
+
location.href = location.href
|
|
973
|
+
})
|
|
974
|
+
}
|
|
975
|
+
<% } %>
|
|
976
|
+
<% if (cloudflare_pub) { %>
|
|
977
|
+
if (document.querySelector("#cloudflare-qr")) {
|
|
978
|
+
document.querySelector("#cloudflare-qr").addEventListener("click", async (e) => {
|
|
979
|
+
await Swal.fire({
|
|
980
|
+
title: "Public Share",
|
|
981
|
+
customClass: {
|
|
982
|
+
popup: "min-popup",
|
|
983
|
+
title: "min-title"
|
|
984
|
+
},
|
|
985
|
+
showConfirmButton: false,
|
|
986
|
+
html: `<div class='min-modal'>
|
|
987
|
+
<div>Access Pinokio from anywhere</div>
|
|
988
|
+
<div>(powered by cloudflare tunnel)</div>
|
|
989
|
+
<div><img src="<%=qr_cloudflare%>"></div>
|
|
990
|
+
<a href="<%=cloudflare_pub%>" target="_blank"><%=cloudflare_pub%></a>
|
|
991
|
+
</div>`
|
|
992
|
+
})
|
|
993
|
+
})
|
|
994
|
+
}
|
|
995
|
+
if (document.querySelector("#cloudflare-stop")) {
|
|
996
|
+
document.querySelector("#cloudflare-stop").addEventListener("click", async (e) => {
|
|
997
|
+
let res = await fetch("/unpublish", {
|
|
998
|
+
method: "post",
|
|
999
|
+
headers: {
|
|
1000
|
+
"Content-Type": "application/json"
|
|
1001
|
+
},
|
|
1002
|
+
body: JSON.stringify({
|
|
1003
|
+
type: "cloudflare"
|
|
1004
|
+
})
|
|
1005
|
+
}).then((res) => {
|
|
1006
|
+
return res.json()
|
|
1007
|
+
})
|
|
1008
|
+
console.log(res)
|
|
1009
|
+
location.href = location.href
|
|
1010
|
+
})
|
|
1011
|
+
}
|
|
1012
|
+
<% } %>
|
|
1013
|
+
if (document.querySelector("#wifi")) {
|
|
1014
|
+
document.querySelector("#wifi").addEventListener("click", async (e) => {
|
|
1015
|
+
document.querySelector("#wifi").classList.add("hidden")
|
|
1016
|
+
document.querySelector("#wifi-starting").classList.remove("hidden")
|
|
1017
|
+
let res = await fetch("/publish", {
|
|
1018
|
+
method: "post",
|
|
1019
|
+
headers: {
|
|
1020
|
+
"Content-Type": "application/json"
|
|
1021
|
+
},
|
|
1022
|
+
body: JSON.stringify({
|
|
1023
|
+
type: "local"
|
|
1024
|
+
})
|
|
1025
|
+
}).then((res) => {
|
|
1026
|
+
return res.json()
|
|
1027
|
+
})
|
|
1028
|
+
console.log(res)
|
|
1029
|
+
location.href = location.href
|
|
1030
|
+
})
|
|
1031
|
+
}
|
|
1032
|
+
if (document.querySelector("#cloudflare")) {
|
|
1033
|
+
document.querySelector("#cloudflare").addEventListener("click", async (e) => {
|
|
1034
|
+
document.querySelector("#cloudflare").classList.add("hidden")
|
|
1035
|
+
document.querySelector("#cloudflare-starting").classList.remove("hidden")
|
|
1036
|
+
let res = await fetch("/publish", {
|
|
1037
|
+
method: "post",
|
|
1038
|
+
headers: {
|
|
1039
|
+
"Content-Type": "application/json"
|
|
1040
|
+
},
|
|
1041
|
+
body: JSON.stringify({
|
|
1042
|
+
type: "cloudflare"
|
|
1043
|
+
})
|
|
1044
|
+
}).then((res) => {
|
|
1045
|
+
return res.json()
|
|
1046
|
+
})
|
|
1047
|
+
console.log(res)
|
|
1048
|
+
location.href = location.href
|
|
1049
|
+
})
|
|
1050
|
+
}
|
|
1051
|
+
<% } %>
|
|
1052
|
+
if (document.querySelector("#back")) {
|
|
1053
|
+
document.querySelector("#back").addEventListener("click", (e) => {
|
|
1054
|
+
history.back()
|
|
1055
|
+
})
|
|
1056
|
+
}
|
|
1057
|
+
if (document.querySelector("#forward")) {
|
|
1058
|
+
document.querySelector("#forward").addEventListener("click", (e) => {
|
|
1059
|
+
history.forward()
|
|
1060
|
+
})
|
|
1061
|
+
}
|
|
1062
|
+
if (document.querySelector("#genlog")) {
|
|
1063
|
+
document.querySelector("#genlog").addEventListener("click", (e) => {
|
|
1064
|
+
e.preventDefault()
|
|
1065
|
+
e.stopPropagation()
|
|
1066
|
+
e.target.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
|
|
1067
|
+
fetch("/pinokio/log", {
|
|
1068
|
+
method: "post",
|
|
1069
|
+
}).then((res) => {
|
|
1070
|
+
console.log("RES", res)
|
|
1071
|
+
let btn = document.querySelector("#genlog")
|
|
1072
|
+
let btn2 = document.querySelector("#downloadlogs")
|
|
1073
|
+
btn2.classList.remove("hidden")
|
|
1074
|
+
btn.classList.add("hidden")
|
|
1075
|
+
btn.innerHTML = '<i class="fa-solid fa-circle-check"></i> Generated!'
|
|
1076
|
+
//btn.classList.add("hidden")
|
|
1077
|
+
})
|
|
1078
|
+
})
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
</script>
|
|
1082
|
+
</body>
|
|
1083
|
+
</html>
|