pinokiod 3.9.3 → 3.9.13

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/:w DELETED
@@ -1,1247 +0,0 @@
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="/filepond.min.css" rel="stylesheet" />
14
- <link href="/filepond-plugin-image-preview.min.css" rel="stylesheet" />
15
- <link href="/filepond-plugin-image-edit.min.css" rel="stylesheet" />
16
- <link href="/style.css" rel="stylesheet"/>
17
- <% if (agent === "electron") { %>
18
- <link href="/electron.css" rel="stylesheet"/>
19
- <% } %>
20
- <style>
21
- .line2 {
22
- display: flex;
23
- align-items: center;
24
- cursor: pointer;
25
- background: rgba(0,0,100,0.04);
26
- }
27
- .line2 a {
28
- text-decoration: none;
29
- color: black;
30
- }
31
- .status {
32
- padding: 10px;
33
- margin: 10px;
34
- border-radius: 10px;
35
- }
36
- .status.offline {
37
- background: silver;
38
- }
39
- .status.online {
40
- background: yellowgreen;
41
- }
42
- .switch {
43
- padding: 10px;
44
- margin: 10px 0;
45
- }
46
- .switch[data-online=true] {
47
- color: yellowgreen;
48
- }
49
- .button {
50
- padding: 10px;
51
- }
52
- .on, .off {
53
- display: flex;
54
- align-items: center;
55
- }
56
- header .runner {
57
- padding: 10px 0 0;
58
- }
59
- .proxy {
60
- padding: 0 10px;
61
- text-align: right;
62
- }
63
- .proxy a {
64
- text-decoration: none;
65
- display: inline-block;
66
- padding: 5px 10px;
67
- border-radius: 2px;
68
- background: black;
69
- color: white;
70
- }
71
- .browser-options-btns {
72
- display: flex;
73
- padding-top: 5px;
74
- }
75
- .browser-options-row {
76
- /*
77
- border-top: 1px solid rgba(0,0,0,0.1);
78
- border-bottom: 1px solid rgba(0,0,0,0.1);
79
- */
80
- display: flex;
81
- padding: 10px;
82
- align-items: flex-start;
83
- }
84
- .browser-options-row h3 {
85
- margin: 0;
86
- font-size: 14px;
87
- margin-bottom: 3px;
88
- }
89
- .browser-options-row .btn.disabled {
90
- opacity: 0.7;
91
- }
92
- .browser-options-row .btn {
93
- font-weight: bold;
94
- width: 100px;
95
- text-align: center;
96
- display: block;
97
- margin-right: 10px;
98
- flex-shrink: 0;
99
- padding: 5px;
100
- }
101
- .badge {
102
- font-size: 12px;
103
- padding: 5px 10px;
104
- background: rgba(0,0,100,0.1);
105
- border-radius: 5px;
106
- display: inline-block;
107
- margin-top: 5px;
108
- }
109
- a.badge {
110
- color: royalblue;
111
- text-decoration: none;
112
- cursor: pointer;
113
- }
114
- .badge a {
115
- color: royalblue;
116
- text-decoration: none;
117
- }
118
- body.dark .btn {
119
- color: white;
120
- border: 1px solid rgba(255,255,255,0.3);
121
- }
122
- body.dark .badge {
123
- background: rgba(255,255,255,0.1);
124
- }
125
- /*
126
- body.dark .browser-options-row {
127
- border-top: 1px solid rgba(255,255,255,0.05);
128
- border-bottom: 1px solid rgba(255,255,255,0.05);
129
- }
130
- */
131
- .context-menu-wrapper {
132
- padding: 2px 0;
133
- background: rgba(0,0,0,0.9);
134
- }
135
- .context-menu {
136
- /*
137
- max-height: 10000px;
138
- overflow: hidden;
139
- transition: max-height 1s ease-in-out;
140
- */
141
- display: flex;
142
- }
143
- .context-menu .btn:hover {
144
- color: cornflowerblue !important;
145
- }
146
- .context-menu .btn {
147
- background: none !important;
148
- border: none !important;
149
- display: block;
150
- width: 80px;
151
- padding: 6px 10px !important;
152
- text-align: left;
153
- }
154
- .context-menu.collapsed {
155
- /*
156
- max-height: 0;
157
- */
158
- display: none;
159
- }
160
- body.dark .open-menu {
161
- background: black !important;
162
- color: white !important;
163
- }
164
- .open-menu {
165
- width: 80px;
166
- border-radius: 0 !important;
167
- background: white !important;
168
- color: black !important;
169
- border: 1px solid rgba(0, 0, 0, 0.3);
170
- }
171
- .open-menu.selected {
172
- border: none !important;
173
- /*
174
- background: none !important;
175
- */
176
- }
177
- .open-menu.selected span {
178
- display: none;
179
- }
180
- @media only screen and (max-width: 480px) {
181
- .btn2 {
182
- padding: 5px;
183
- font-size: 11px;
184
- }
185
- .nav-btns {
186
- flex-grow: 1;
187
- justify-content: center;
188
- padding: 0;
189
- }
190
- }
191
- </style>
192
- <script src="/hotkeys.min.js"></script>
193
- <script src="/sweetalert2.js"></script>
194
- <script src="/noty.js"></script>
195
- <script src="/notyq.js"></script>
196
- <script src="/xterm.js"></script>
197
- <script src="/xterm-addon-fit.js"></script>
198
- <script src="/xterm-addon-web-links.js"></script>
199
- <script src="/xterm-theme.js"></script>
200
- <script src="/Socket.js"></script>
201
- <script src="/install.js"></script>
202
- <script src="/common.js"></script>
203
- <script src="/opener.js"></script>
204
- <script src="/nav.js"></script>
205
- <script src="/fuse.js"></script>
206
- <script src="/report.js"></script>
207
- <script src="/filepond-plugin-file-validate-type.min.js"></script>
208
- <script src="/filepond-plugin-image-exif-orientation.min.js"></script>
209
- <script src="/filepond-plugin-image-preview.min.js"></script>
210
- <script src="/filepond-plugin-image-edit.min.js"></script>
211
- <script src="/filepond-plugin-image-crop.min.js"></script>
212
- <script src="/filepond-plugin-image-resize.min.js"></script>
213
- <script src="/filepond-plugin-image-transform.min.js"></script>
214
- <script src="/filepond.min.js"></script>
215
- <script src="/fscreator.js"></script>
216
- <script src="/fseditor.js"></script>
217
- </head>
218
- <body class='<%=theme%>'>
219
- <% if (error) { %>
220
- <nav class='error-message'>
221
- <div><%=error%></div>
222
- <div class='flexible'></div>
223
- <a class='btn' target="_blank" href="<%=install%>">Download</a>
224
- </nav>
225
- <% } %>
226
- <!--
227
- <header class='grabbable'>
228
- -->
229
- <header class='navheader grabbable'>
230
- <h1>
231
- <% if (ishome) { %>
232
- <a class='home' href="/"><i class="fa-solid fa-house"></i></a>
233
- <button class='btn2' id='back'><div><i class="fa-solid fa-chevron-left"></i></div><div>Prev</div></button>
234
- <button class='btn2' id='forward'><div><i class="fa-solid fa-chevron-right"></i></div><div>Next</div></button>
235
- <a class='btn2 create-new' id='create-new-folder'><div><i class='fa-solid fa-plus'></i></div><div>New</div></a>
236
- <!--
237
- <a href="/new" class='btn2'><div><i class='fa-solid fa-folder-plus'></i></div><div>Create</div></a>
238
- -->
239
- <a class='btn2' id='explore' href="/?mode=explore"><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
240
- <a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Network</div></a>
241
- <a href="/connect" class='btn2'><div><i class="fa-solid fa-circle-user"></i></div><div>Connect</div></a>
242
- <!--
243
- <button id='newfolder' class='btn2'><div><i class="fa-solid fa-folder-plus"></i></div><div>New Folder</div></button>
244
- -->
245
- <% } %>
246
- <% paths.forEach((path) => { %>
247
- <% if (path.action) { %>
248
- <a class='path nav-button' id="<%=path.id%>" onclick="<%=path.action%>"><%-path.name%></a>
249
- <% } else if (path.path) { %>
250
- <a class='path' href="<%=path.path%>"><%-path.name%></a>
251
- <% } %>
252
- <% }) %>
253
- <form class='search'>
254
- <% if (display.includes("form")) { %>
255
- <input type='search' class="flexible" placeholder='Filter downloaded apps'>
256
- <% } else { %>
257
- <% } %>
258
- </form>
259
- <% if (ishome) { %>
260
- <div class='nav-btns'>
261
- <a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
262
- <% if (agent === "electron") { %>
263
- <a class='btn2' data-filepath="<%=filepath%>"><div><i class="fa-regular fa-folder-open"></i></div><div>Files</div></a>
264
- <% } %>
265
- <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
266
- <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>
267
- <a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
268
- <% if (agent === "electron") { %>
269
- <a href="/" target="_blank" class='btn2' features="browser"><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
270
- <% } else { %>
271
- <a href="/" target="_blank" class='btn2'><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
272
- <% } %>
273
- <button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
274
- </div>
275
- <% } %>
276
- </h1>
277
- <% if (!ishome) { %>
278
- <div class='runner'>
279
- <button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> View Folder</button>
280
- </div>
281
- <% } %>
282
- <% if (display.includes("dependencies") && config) { %>
283
- <div class='dependencies'>
284
- <h2>Prerequisites</h2>
285
- <div class='item'>Download and install the following dependencies first</div>
286
- <div class='requirements'>
287
- <% config.dependencies.forEach((dep) => { %>
288
- <% if (dep.downloaded) { %>
289
- <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>
290
- <% } else { %>
291
- <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>
292
- <% } %>
293
- <% }) %>
294
- </div>
295
- </div>
296
- <% } %>
297
- </header>
298
- <main>
299
- <div id='terminal' class='hidden'></div>
300
- <div class='container'>
301
- <% if (ishome) { %>
302
- <% if (running.length === 0 && notRunning.length === 0) { %>
303
- <% } else { %>
304
- <% if (false) { %>
305
- <div class='browser-options'>
306
- <% if (agent === "electron") { %>
307
- <div class='browser-options-row'>
308
- <% if (agent === "electron") { %>
309
- <a href="/" target="_blank" class='btn' features="browser"><div><i class="fa-solid fa-square-up-right"></i> Open</div></a>
310
- <% } else { %>
311
- <a href="/" target="_blank" class='btn'><div><i class="fa-solid fa-square-up-right"></i> Open</div></a>
312
- <% } %>
313
- <div class='flexible'>
314
- <h3><i class="fa-solid fa-bolt"></i> Instant Launch</h3>
315
- <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>
316
- </div>
317
- </div>
318
- <% } %>
319
- <div class='browser-options-row'>
320
- <a href="/network" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
321
- <div class='flexible'>
322
- <h3><i class="fa-solid fa-wifi"></i> Local Sharing</h3>
323
- <div>Serve Pinokio, installed apps, and even external apps (example: Ollama) to any device on the same network.</div>
324
- </div>
325
- </div>
326
- <div class='browser-options-row hidden'>
327
- <% if (cloudflare_pub) { %>
328
- <a id='cloudflare-stop' class='btn'><div><i class="fa-solid fa-stop"></i> Stop</div></a>
329
- <div class='flexible'>
330
- <h3>Public Share</h3>
331
- <div>Open up your Pinokio server to the open internet (anyone with the URL can access)</div>
332
- <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>
333
- <a id='cloudflare-qr' class='badge'><i class="fa-solid fa-qrcode"></i> Scan QR Code</a>
334
- </div>
335
- <% } else { %>
336
- <a id='cloudflare' class='btn'><div><i class="fa-solid fa-play"></i> Start</div></a>
337
- <a id='cloudflare-starting' class='btn disabled hidden'><div><i class="fa-solid fa-circle-notch fa-spin"></i> Starting</div></a>
338
- <div class='flexible'>
339
- <h3>Public Share</h3>
340
- <div>Open up your Pinokio server to the open internet (anyone with the URL can access)</div>
341
- </div>
342
- <% } %>
343
- </div>
344
- </div>
345
- <% } %>
346
- <% } %>
347
- <% if (running.length > 0) { %>
348
- <div class='running-apps'>
349
- <!--
350
- <div class='header-label'>Running</div>
351
- -->
352
- <% running.forEach((item) => { %>
353
- <a href="<%=item.browser_url%>" data-description="<%=item.description%>" data-index="<%=item.index%>" data-name="<%=item.name%>" data-title="<%=item.name%>" data-uri="<%=item.uri%>" data-icon="<%=item.icon%>" data-path="<%=item.path%>" data-iconpath="<%=item.iconpath ? item.iconpath : ''%>" class='line align-top'>
354
- <h3>
355
- <div class='item-icon'>
356
- <% if (item.icon) { %>
357
- <img src="<%=item.icon%>">
358
- <% } else { %>
359
- <% if (theme === 'dark') { %>
360
- <img src="/pinokio-white.png">
361
- <% } else { %>
362
- <img src="/pinokio-black.png">
363
- <% } %>
364
- <% } %>
365
- </div>
366
- <div class='col'>
367
- <div class='uri'><i class="fa-regular fa-folder"></i><%=item.url%></div>
368
- <div class='title'><%=item.name%></div>
369
- <div class='description'><%=item.description%></div>
370
- <div class='menu-btns'>
371
- <div>
372
- <button class='btn open-menu'>
373
- <i class="fa-solid fa-bars"></i><span> Menu</span>
374
- </button>
375
- <div class='context-menu collapsed'>
376
- <div class='context-menu-wrapper'>
377
- <button class='btn browse' data-src="<%=item.browser_url%>/browse">
378
- <i class='fa-regular fa-folder-open'></i> View
379
- </button>
380
- <button class='btn copy-menu' data-src="<%=item.browser_url%>/browse">
381
- <i class='fa-solid fa-copy'></i> Copy
382
- </button>
383
- </div>
384
- </div>
385
- </div>
386
- <div class='flexible'></div>
387
- <% if (item.running_scripts) { %>
388
- <% item.running_scripts.forEach((s) => { %>
389
- <button class='btn shutdown' data-src="<%=s.path%>">
390
- <i class="fa-solid fa-stop"></i> Stop <%=s.name%>&nbsp;
391
- <i class='fa-solid fa-spin fa-circle-notch'></i>
392
- </button>
393
- <% }) %>
394
- <% } %>
395
- </div>
396
- <% if (item.shortcuts && item.shortcuts.length > 0) { %>
397
- <div class='btns'>
398
- <% item.shortcuts.forEach((btn) => { %>
399
- <% if (btn.btn) { %>
400
- <button data-action="<%=btn.action ? JSON.stringify(btn.action) : ''%>" class='btn menu-btn'><%-btn.btn%></button>
401
- <% } %>
402
- <% }) %>
403
- </div>
404
- <% } %>
405
- </div>
406
- <!--
407
- <div class='spinner'>
408
- <i class="fa-solid fa-chevron-right"></i>
409
- </div>
410
- -->
411
- </h3>
412
- </a>
413
- <% }) %>
414
- </div>
415
- <% } %>
416
- <% if (notRunning.length > 0) { %>
417
- <div class='not-running-apps'>
418
- <!--
419
- <div class='header-label'>Not Running</div>
420
- -->
421
- <% notRunning.forEach((item) => { %>
422
- <a href="<%=item.browser_url%>" data-description="<%=item.description%>" data-index="<%=item.index%>" data-name="<%=item.name%>" data-title="<%=item.name%>" data-uri="<%=item.uri%>" data-icon="<%=item.icon%>" data-path="<%=item.path%>" data-iconpath="<%=item.iconpath ? item.iconpath : ''%>" class='line align-top'>
423
- <h3>
424
- <div class='item-icon'>
425
- <% if (item.icon) { %>
426
- <img src="<%=item.icon%>">
427
- <% } else { %>
428
- <% if (theme === 'dark') { %>
429
- <img src="/pinokio-white.png">
430
- <% } else { %>
431
- <img src="/pinokio-black.png">
432
- <% } %>
433
- <% } %>
434
- </div>
435
- <div class='col'>
436
- <div class='uri'><i class="fa-regular fa-folder"></i><%=item.url%></div>
437
- <div class='title'><%=item.name%></div>
438
- <div class='description'><%=item.description%></div>
439
- <div class='menu-btns'>
440
- <button class='btn open-menu'>
441
- <i class="fa-solid fa-bars"></i><span> Menu</span>
442
- </button>
443
- <div class='context-menu collapsed'>
444
- <div class='context-menu-wrapper'>
445
- <button class='btn browse' data-src="<%=item.browser_url%>/browse">
446
- <i class='fa-regular fa-folder-open'></i> View
447
- </button>
448
- <button class='btn copy-menu' data-src="<%=item.browser_url%>/browse">
449
- <i class='fa-solid fa-copy'></i> Copy
450
- </button>
451
- <button class='btn move-menu' data-src="<%=item.browser_url%>/browse">
452
- <i class="fa-solid fa-pencil"></i> Move
453
- </button>
454
- <button class='btn edit-menu' data-src="<%=item.browser_url%>/browse">
455
- <i class='fa-solid fa-pen-to-square'></i> Edit
456
- </button>
457
- <button class='btn del' data-src="<%=item.url%>">
458
- <i class="fa-solid fa-trash-can"></i> Delete
459
- </button>
460
- </div>
461
- </div>
462
- </div>
463
- <div class='fiexible'></div>
464
- <% if (item.shortcuts && item.shortcuts.length > 0) { %>
465
- <div class='btns'>
466
- <% item.shortcuts.forEach((btn) => { %>
467
- <% if (btn.btn) { %>
468
- <button data-action="<%=btn.action ? JSON.stringify(btn.action) : ''%>" class='btn menu-btn'><%-btn.btn%></button>
469
- <% } %>
470
- <% }) %>
471
- </div>
472
- <% } %>
473
- </div>
474
- <!--
475
- <div class='spinner'>
476
- <i class="fa-solid fa-chevron-right"></i>
477
- </div>
478
- -->
479
- </h3>
480
- </a>
481
- <% }) %>
482
- </div>
483
- <% } %>
484
- <% if (running.length === 0 && notRunning.length === 0) { %>
485
- <div class='placeholder'>
486
- <h1>Welcome.</h1>
487
- <br>
488
- <div>Get started by installing some Pinokio scripts.</div>
489
- <a href="/?mode=explore" class='btn'><i class="fa-solid fa-globe"></i> Visit Discover Page</a>
490
- </div>
491
- <% } %>
492
- <% } else { %>
493
- <% items.forEach((item, index) => { %>
494
- <a data-description="<%=item.description%>" data-index="<%=index%>" data-name="<%=item.name%>" data-uri="<%=item.uri%>" class='line thick' href="<%=item.url%>">
495
- <h3>
496
- <% if (item.icon) { %>
497
- <i class="<%=item.icon%>"></i>
498
- <% } else { %>
499
- <i class="fa-regular fa-folder"></i>
500
- <% } %>
501
- <%=item.name%>
502
- </h3>
503
- <div class='description'><%=item.description%></div>
504
- </a>
505
- <% }) %>
506
- <% } %>
507
- <% if (readme) { %>
508
- <div class='readme markdown-body'>
509
- <div class='content'><%-readme%></div>
510
- </div>
511
- <% } %>
512
- <% if (display.includes("onboarding")) { %>
513
- <!--
514
- <div class='container'>
515
- <div class='content'>
516
- <h2>Quickstart</h2>
517
- <div>Install llama</div>
518
- <br>
519
- <button class='btn' id='llama'>Install</button>
520
- </div>
521
- </div>
522
- -->
523
- <% } %>
524
- </div>
525
- </main>
526
- <script>
527
- let paths = location.pathname.split("/").filter(x=>x)
528
- var term
529
- const n = new N()
530
- let socket = new Socket()
531
- const pull = async () => {
532
- if (!term) {
533
- <% if (theme === "dark") { %>
534
- term = await createTerm(xtermTheme.FrontEndDelight)
535
- <% } else { %>
536
- term = await createTerm(xtermTheme.Tomorrow)
537
- <% } %>
538
- }
539
- socket.close()
540
- await new Promise((resolve, reject) => {
541
- let cwd
542
- let chunks = location.pathname.split("/").filter((x) => { return x })
543
- if (chunks.length > 0) {
544
- //cwd = chunks.slice(1).join("/")
545
- cwd = "~/" + chunks.join("/")
546
- } else {
547
- cwd = "."
548
- }
549
- socket.run({
550
- method: "shell.run",
551
- params: {
552
- message: `git pull`,
553
- // path: "<%=uri%>",//cwd
554
- path: cwd
555
- }
556
- }, (packet) => {
557
- if (packet.type === 'stream') {
558
- term.write(packet.data.raw)
559
- } else if (packet.type === "result") {
560
- resolve()
561
- } else if (packet.type === "error") {
562
- n.Noty({
563
- text: packet.data
564
- })
565
- }
566
- })
567
- })
568
- <% if (config && config.update) { %>
569
- n.Noty({
570
- text: "Success! An update script exists. Click to visit and run the update script!",
571
- type: "success",
572
- callbacks: {
573
- onClose: () => {
574
- location.href = "<%=config.update%>"
575
- }
576
- }
577
- })
578
- <% } else { %>
579
- n.Noty({
580
- text: "Success! Click to refresh.",
581
- type: "success",
582
- callbacks: {
583
- onClose: () => {
584
- location.href = location.href
585
- }
586
- }
587
- })
588
- <% } %>
589
- }
590
- <% if (display.includes("onboarding")) { %>
591
- //document.querySelector("#llama").addEventListener("click", async (e) => {
592
- // if (!term) term = createTerm()
593
- // await install("llama", "https://github.com/malfunctionize/lla", term, socket)
594
- //})
595
- <% } %>
596
- <% if (display.includes("form")) { %>
597
- let list = []
598
- document.querySelectorAll(".line").forEach((el, index) => {
599
- list.push({
600
- index: parseInt(el.getAttribute("data-index")),
601
- name: el.getAttribute("data-name"),
602
- description: el.getAttribute("data-description"),
603
- uri: el.getAttribute("data-uri")
604
- })
605
- })
606
- const search = (items, value) => {
607
- let filtered = []
608
- for(let i=0; i<items.length; i++) {
609
- let item = items[i]
610
- let re = new RegExp(value, "i")
611
- if (re.test(item.name)) {
612
- filtered.push({ item })
613
- } else if (re.test(item.description)) {
614
- filtered.push({ item })
615
- } else if (re.test(item.uri)) {
616
- filtered.push({ item })
617
- }
618
- }
619
- return filtered
620
- }
621
- //const fuse = new Fuse(list, {
622
- // threshold: 0.3,
623
- // keys: [{
624
- // name: "name",
625
- // weight: 5,
626
- // }, {
627
- // name: "description",
628
- // weight: 1,
629
- // }],
630
- // includeScore: true,
631
- // includeMatches: true
632
- //})
633
-
634
-
635
- let selectedIndex = -1
636
- let selectedBtnIndex = 0
637
- let filteredCount = list.length
638
- let filteredBtnsCount = 0
639
-
640
- const renderSearch = () => {
641
- let target = document.querySelector("form input[type=search]")
642
- let result
643
- if (target.value.trim().length === 0) {
644
- result = list.map((i, index) => {
645
- return { item: i }
646
- })
647
- } else {
648
- result = search(list, target.value)
649
- }
650
- let all = document.querySelectorAll(".line")
651
- for(let el of all) {
652
- el.classList.add("hidden")
653
- el.classList.remove("selected")
654
- }
655
-
656
- filteredCount = result.length
657
- for(let i=0; i<result.length; i++) {
658
- let selector = result[i]
659
- //let el = document.querySelector(".line[data-name='" + selector.item.name + "']")
660
- let el = document.querySelector(".line[data-index='" + selector.item.index + "']")
661
- el.classList.remove("hidden")
662
- if (i === selectedIndex) {
663
- el.classList.add("selected")
664
- let btns = el.querySelectorAll(".btns a")
665
- filteredBtnsCount = btns.length
666
- btns.forEach((_el, j) => {
667
- if (selectedBtnIndex === j) {
668
- _el.classList.add("selected")
669
- } else {
670
- _el.classList.remove("selected")
671
- }
672
- })
673
- } else {
674
- el.classList.remove("selected")
675
- let btns = el.querySelectorAll(".btns a")
676
- btns.forEach((_el, j) => {
677
- _el.classList.remove("selected")
678
- })
679
- }
680
- }
681
-
682
- }
683
-
684
- renderSearch()
685
-
686
-
687
- document.querySelector("form input[type=search]").addEventListener("input", (e) => {
688
- selectedIndex = 0
689
- selectedBtnIndex = 0
690
- renderSearch()
691
- /*
692
- if (e.target.value.trim().length === 0) {
693
- let all = document.querySelectorAll(".line")
694
- for(let el of all) {
695
- el.classList.remove("hidden")
696
- }
697
- } else {
698
- let all = document.querySelectorAll(".line")
699
- for(let el of all) {
700
- el.classList.add("hidden")
701
- }
702
-
703
- //let result = fuse.search(e.target.value)
704
- let result = search(list, e.target.value)
705
- // result.sort((x, y) => {
706
- // return y.score - x.score
707
- // })
708
- let i = 0
709
- //for(let selector of result) {
710
- for(let i=0; i<result.length; i++) {
711
- let selector = result[i]
712
- let el = document.querySelector(".line[data-name='" + selector.item.name + "']")
713
- el.classList.remove("hidden")
714
- if (i === 0) {
715
- el.classList.add("selected")
716
- }
717
- }
718
- }
719
- */
720
- })
721
- document.querySelector("form input[type=search]").focus()
722
- <% } %>
723
-
724
-
725
- // if (el) {
726
- // let url = el.getAttribute("data-url")
727
- // if (url) {
728
- // let target = el.getAttribute("data-target")
729
- // if (target && target.length > 0) {
730
- // let agent = el.getAttribute("data-agent")
731
- // if (agent && agent.length > 0) {
732
- // window.open(url, target, agent)
733
- // } else {
734
- // window.open(url, target)
735
- // }
736
- // } else {
737
- // location.href = url
738
- // }
739
- // }
740
- // }
741
- //document.querySelector(".runner").addEventListener("click", async (e) => {
742
- // let el = e.target.closest(".btn")
743
- // if (!el) {
744
- // if (el.classList.contains("btn")) {
745
- // el = e.target
746
- // }
747
- // }
748
- //
749
- // if (el) {
750
- // let url = el.getAttribute("data-url")
751
- // if (url) {
752
- // let target = el.getAttribute("data-target")
753
- // if (target && target.length > 0) {
754
- // let agent = el.getAttribute("data-agent")
755
- // if (agent && agent.length > 0) {
756
- // window.open(url, target, agent)
757
- // } else {
758
- // window.open(url, target)
759
- // }
760
- // } else {
761
- // location.href = url
762
- // }
763
- // }
764
- // }
765
- //})
766
- <% if (display.includes("install")) { %>
767
- document.querySelector("#install").addEventListener("click", async (e) => {
768
- location.href = e.target.getAttribute("data-url")
769
- })
770
- <% } %>
771
- //Reporter()
772
- /*
773
- <% if (display.includes("dependencies")) { %>
774
- document.querySelector(".requirements").addEventListener("click", (e) => {
775
- e.preventDefault()
776
- e.stopPropagation()
777
- let el = e.target.closest(".opener")
778
- if (!el) {
779
- if (e.target.classList.contains("opener")) {
780
- el = e.target
781
- }
782
- }
783
- if (el) {
784
- window.open(el.getAttribute("data-href"), "_blank", "app")
785
- }
786
- })
787
- <% } %>
788
- */
789
- let params = new URLSearchParams(location.search)
790
- let selected = params.get("selected")
791
- if (selected) {
792
- document.querySelector("form input[type=search]").value = selected
793
- document.querySelector("form input[type=search]").dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
794
- }
795
- if (document.querySelector("form input[type=search]")) {
796
- document.querySelector("form input[type=search]").addEventListener("input", (e) => {
797
- let p
798
- if (e.target.value && e.target.value.trim().length > 0) {
799
- p = location.pathname + "?selected=" + e.target.value
800
- } else {
801
- p = location.pathname
802
- }
803
- window.history.pushState({ path: p }, '', p);
804
- })
805
- }
806
- <% if (ishome) { %>
807
- // if launch_complete is true => already finished launching so no need to refresh
808
- // if launch_complete is false => not finished launching. wait until it's complete, and then refresh
809
- // autolaunch display update
810
- <% if (!launch_complete) { %>
811
- let interval = setInterval(async () => {
812
- let res = await fetch("/pinokio/info").then((res) => {
813
- return res.json()
814
- })
815
- if (res.launch_complete) {
816
- console.log("launched")
817
- clearInterval(interval)
818
- location.href = location.href
819
- } else {
820
- console.log("not yet launched")
821
- }
822
- }, 1000)
823
- <% } %>
824
- document.addEventListener("keydown", (e) => {
825
- e = e || window.event;
826
- if (e.key === "ArrowUp") {
827
- console.log("up arrow pressed");
828
- selectedIndex = Math.max(selectedIndex-1, 0)
829
- selectedBtnIndex = 0
830
- renderSearch()
831
- let selected = document.querySelector(".line.selected")
832
- selected.scrollIntoView(false)
833
- //
834
- } else if (e.key === "ArrowDown") {
835
- console.log("before selectedIndex", selectedIndex)
836
- selectedIndex = Math.min(filteredCount-1, selectedIndex+1)
837
- selectedBtnIndex = 0
838
- console.log("after selectedIndex", selectedIndex)
839
- renderSearch()
840
- console.log("down arrow pressed");
841
- let selected = document.querySelector(".line.selected")
842
- selected.scrollIntoView(false)
843
- } else if (e.key === "ArrowLeft") {
844
- selectedBtnIndex = Math.max(selectedBtnIndex-1, 0)
845
- console.log("left arrow pressed");
846
- console.log("selectedBtnIndex", selectedBtnIndex)
847
- renderSearch()
848
- } else if (e.key === "ArrowRight") {
849
- console.log("right arrow pressed");
850
- selectedBtnIndex = Math.min(filteredBtnsCount-1, selectedBtnIndex+1)
851
- console.log("selectedBtnIndex", selectedBtnIndex)
852
- renderSearch()
853
- } else if (e.key === "Enter") {
854
- //let selected = document.querySelector(".line.selected:not(.hidden) .btns a.selected")
855
- //let selected = document.querySelector(".line.selected:not(.hidden) .title a")
856
- let selected = document.querySelector(".line.selected:not(.hidden)")
857
- console.log("selected", selected)
858
- if (selected) {
859
- e.preventDefault()
860
- e.stopPropagation()
861
- selected.click()
862
- }
863
- }
864
- });
865
- document.addEventListener("click", async (e) => {
866
- if (e.target.classList.contains("shutdown")) {
867
- target = e.target
868
- } else {
869
- target = e.target.closest(".shutdown")
870
- }
871
- if (target) {
872
- e.preventDefault()
873
- e.stopPropagation()
874
- let src = target.getAttribute("data-src")
875
- console.log("src", src)
876
-
877
- socket.run({
878
- method: "kernel.api.stop",
879
- params: {
880
- uri: "~/" + src
881
- }
882
- }, (packet) => {
883
- console.log("packet", packet)
884
- if (packet.type === "result") {
885
- socket.close()
886
- target.querySelector("i.fa-stop").className = "fa-solid fa-check"
887
- target.querySelector("i.fa-spin").classList.add("hidden")
888
- n.Noty({
889
- text: `stopped ${src}`,
890
- silent: true
891
- })
892
- setTimeout(() => {
893
- location.href = location.href
894
- }, 500)
895
- }
896
- })
897
-
898
- return
899
- }
900
- if (e.target.classList.contains("open-menu")) {
901
- target = e.target
902
- } else {
903
- target = e.target.closest(".open-menu")
904
- }
905
- if (target) {
906
- e.preventDefault()
907
- e.stopPropagation()
908
- let contextMenu = target.closest(".col").querySelector(".context-menu").classList.toggle("collapsed")
909
- target.classList.toggle("selected")
910
- return
911
- }
912
-
913
- if (e.target.classList.contains("move-menu")) {
914
- target = e.target
915
- } else {
916
- target = e.target.closest(".move-menu")
917
- }
918
- if (target) {
919
- e.preventDefault()
920
- e.stopPropagation()
921
- let line = target.closest(".line")
922
- let title = line.getAttribute("data-title")
923
- let icon = line.getAttribute("data-icon")
924
- let iconpath = line.getAttribute("data-iconpath")
925
- let path = line.getAttribute("data-path")
926
- let description = line.getAttribute("data-description")
927
- await FSEditor({
928
- title,
929
- description,
930
- old_path: path,
931
- icon,
932
- iconpath,
933
- move: true,
934
- edit: true,
935
- redirect: (new_path) => {
936
- return location.href
937
- }
938
- })
939
- return
940
- }
941
-
942
- if (e.target.classList.contains("copy-menu")) {
943
- target = e.target
944
- } else {
945
- target = e.target.closest(".copy-menu")
946
- }
947
- if (target) {
948
- e.preventDefault()
949
- e.stopPropagation()
950
- let line = target.closest(".line")
951
- let title = line.getAttribute("data-title")
952
- let icon = line.getAttribute("data-icon")
953
- let iconpath = line.getAttribute("data-iconpath")
954
- let path = line.getAttribute("data-path")
955
- let description = line.getAttribute("data-description")
956
- await FSEditor({
957
- title,
958
- description,
959
- old_path: path,
960
- icon,
961
- iconpath,
962
- copy: true,
963
- edit: true,
964
- redirect: (new_path) => {
965
- return location.href
966
- }
967
- })
968
- return
969
- }
970
-
971
- if (e.target.classList.contains("edit-menu")) {
972
- target = e.target
973
- } else {
974
- target = e.target.closest(".edit-menu")
975
- }
976
- if (target) {
977
- e.preventDefault()
978
- e.stopPropagation()
979
- let line = target.closest(".line")
980
- let title = line.getAttribute("data-title")
981
- let icon = line.getAttribute("data-icon")
982
- let iconpath = line.getAttribute("data-iconpath")
983
- let path = line.getAttribute("data-path")
984
- let description = line.getAttribute("data-description")
985
- await FSEditor({
986
- title,
987
- description,
988
- old_path: path,
989
- icon,
990
- iconpath,
991
- edit: true,
992
- redirect: (new_path) => {
993
- return location.href
994
- }
995
- })
996
- return
997
- }
998
-
999
-
1000
-
1001
-
1002
- if (e.target.classList.contains("browse")) {
1003
- target = e.target
1004
- } else {
1005
- target = e.target.closest(".browse")
1006
- }
1007
- if (target) {
1008
- e.preventDefault()
1009
- e.stopPropagation()
1010
- let src = target.getAttribute("data-src")
1011
- location.href = src
1012
- return
1013
- }
1014
-
1015
-
1016
- // delete
1017
- if (e.target.classList.contains("del")) {
1018
- target = e.target
1019
- } else {
1020
- target = e.target.closest(".del")
1021
- }
1022
- if (target) {
1023
- e.preventDefault()
1024
- e.stopPropagation()
1025
- let confirmed = confirm("Are you sure you want to delete the folder? All files in the folder will be gone.")
1026
- if (confirmed) {
1027
- let itemEl = target.closest(".line[data-uri]")
1028
- let name = itemEl.getAttribute("data-uri")
1029
- console.log("delete", name)
1030
- Swal.fire({
1031
- html: '<i class="fa-solid fa-circle-notch fa-spin"></i> Deleting',
1032
- customClass: {
1033
- container: "loader-container",
1034
- popup: "loader-popup",
1035
- htmlContainer: "loader-dialog",
1036
- footer: "hidden",
1037
- actions: "hidden"
1038
- }
1039
- });
1040
- let res = await fetch("/pinokio/delete", {
1041
- method: "post",
1042
- headers: {
1043
- "Content-Type": "application/json"
1044
- },
1045
- body: JSON.stringify({ name })
1046
- }).then((res) => {
1047
- return res.json()
1048
- })
1049
- console.log("res", res)
1050
- Swal.close()
1051
- if (res) {
1052
- if (res.success) {
1053
- location.href = "/"
1054
- } else if (res.error) {
1055
- alert(res.error)
1056
- }
1057
- }
1058
- } else {
1059
- }
1060
- return
1061
- }
1062
-
1063
-
1064
-
1065
- if (document.querySelector(".container")) {
1066
- document.querySelector(".container").addEventListener("click", async (e) => {
1067
- //let el = e.target.closest(".menu-btn")
1068
- //if (!el) {
1069
- // if (el.classList.contains("menu-btn")) {
1070
- // el = e.target
1071
- // }
1072
- //}
1073
-
1074
- let el
1075
- if (e.target.classList.contains("menu-btn")) {
1076
- el = e.target
1077
- } else {
1078
- if (e.target.closest(".menu-btn")) {
1079
- el = e.target
1080
- }
1081
- }
1082
-
1083
- console.log("EL", el)
1084
-
1085
- if (el) {
1086
- e.preventDefault()
1087
- e.stopPropagation()
1088
- let actionStr = el.getAttribute("data-action")
1089
- if (actionStr) {
1090
- let action = JSON.parse(actionStr)
1091
- console.log("action", action)
1092
- if (action.method === "stop" && action.uri) {
1093
- socket.run({
1094
- method: "kernel.api.stop",
1095
- params: {
1096
- uri: action.uri//"~" + location.pathname
1097
- }
1098
- }, (packet) => {
1099
- console.log("packet", packet)
1100
- if (packet.type === "result") {
1101
- socket.close()
1102
- location.href = location.href
1103
- }
1104
- })
1105
- return
1106
- }
1107
- }
1108
-
1109
- }
1110
- })
1111
- }
1112
-
1113
-
1114
-
1115
-
1116
- /*
1117
- target = (e.target.classList.contains(".btn") ? e.target : e.target.closest(".btn"))
1118
- if (target) {
1119
- target.classList.add("clicked")
1120
- document.querySelectorAll(".line .btns .btn").forEach((e) => {
1121
- e.classList.remove("selected")
1122
- })
1123
- target.classList.add("selected")
1124
- target.closest(".line").classList.add("selected")
1125
- return
1126
- }
1127
- */
1128
-
1129
-
1130
- })
1131
- <% if (proxy) { %>
1132
- if (document.querySelector("#wifi-qr")) {
1133
- document.querySelector("#wifi-qr").addEventListener("click", async (e) => {
1134
- await Swal.fire({
1135
- title: "Local Share",
1136
- customClass: {
1137
- popup: "min-popup",
1138
- title: "min-title"
1139
- },
1140
- showConfirmButton: false,
1141
- html: `<div class='min-modal'>
1142
- <div>Access Pinokio from</div>
1143
- <div>any local network device</div>
1144
- <div><img src="<%=qr%>"></div>
1145
- <a href="<%=proxy.proxy%>" target="_blank"><%=proxy.proxy%></a>
1146
- </div>`
1147
- })
1148
- })
1149
- }
1150
- if (document.querySelector("#wifi-stop")) {
1151
- document.querySelector("#wifi-stop").addEventListener("click", async (e) => {
1152
- let res = await fetch("/unpublish", {
1153
- method: "post",
1154
- headers: {
1155
- "Content-Type": "application/json"
1156
- },
1157
- body: JSON.stringify({
1158
- type: "local"
1159
- })
1160
- }).then((res) => {
1161
- return res.json()
1162
- })
1163
- console.log(res)
1164
- location.href = location.href
1165
- })
1166
- }
1167
- <% } %>
1168
- <% if (cloudflare_pub) { %>
1169
- if (document.querySelector("#cloudflare-qr")) {
1170
- document.querySelector("#cloudflare-qr").addEventListener("click", async (e) => {
1171
- await Swal.fire({
1172
- title: "Public Share",
1173
- customClass: {
1174
- popup: "min-popup",
1175
- title: "min-title"
1176
- },
1177
- showConfirmButton: false,
1178
- html: `<div class='min-modal'>
1179
- <div>Access Pinokio from anywhere</div>
1180
- <div>(powered by cloudflare tunnel)</div>
1181
- <div><img src="<%=qr_cloudflare%>"></div>
1182
- <a href="<%=cloudflare_pub%>" target="_blank"><%=cloudflare_pub%></a>
1183
- </div>`
1184
- })
1185
- })
1186
- }
1187
- if (document.querySelector("#cloudflare-stop")) {
1188
- document.querySelector("#cloudflare-stop").addEventListener("click", async (e) => {
1189
- let res = await fetch("/unpublish", {
1190
- method: "post",
1191
- headers: {
1192
- "Content-Type": "application/json"
1193
- },
1194
- body: JSON.stringify({
1195
- type: "cloudflare"
1196
- })
1197
- }).then((res) => {
1198
- return res.json()
1199
- })
1200
- console.log(res)
1201
- location.href = location.href
1202
- })
1203
- }
1204
- <% } %>
1205
- if (document.querySelector("#wifi")) {
1206
- document.querySelector("#wifi").addEventListener("click", async (e) => {
1207
- document.querySelector("#wifi").classList.add("hidden")
1208
- document.querySelector("#wifi-starting").classList.remove("hidden")
1209
- let res = await fetch("/publish", {
1210
- method: "post",
1211
- headers: {
1212
- "Content-Type": "application/json"
1213
- },
1214
- body: JSON.stringify({
1215
- type: "local"
1216
- })
1217
- }).then((res) => {
1218
- return res.json()
1219
- })
1220
- console.log(res)
1221
- location.href = location.href
1222
- })
1223
- }
1224
- if (document.querySelector("#cloudflare")) {
1225
- document.querySelector("#cloudflare").addEventListener("click", async (e) => {
1226
- document.querySelector("#cloudflare").classList.add("hidden")
1227
- document.querySelector("#cloudflare-starting").classList.remove("hidden")
1228
- let res = await fetch("/publish", {
1229
- method: "post",
1230
- headers: {
1231
- "Content-Type": "application/json"
1232
- },
1233
- body: JSON.stringify({
1234
- type: "cloudflare"
1235
- })
1236
- }).then((res) => {
1237
- return res.json()
1238
- })
1239
- console.log(res)
1240
- location.href = location.href
1241
- })
1242
- }
1243
- <% } %>
1244
-
1245
- </script>
1246
- </body>
1247
- </html>