pinokiod 3.25.0 → 3.26.0

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.
@@ -207,6 +207,30 @@ body.dark .btn {
207
207
  .tab-header h3 i {
208
208
  font-size: 18px;
209
209
  }
210
+ header {
211
+ padding: 50px 40px 0;
212
+ display: flex;
213
+ gap: 10px;
214
+ }
215
+ header h1 {
216
+ font-size: 40px;
217
+ }
218
+ .pulling {
219
+ display: flex;
220
+ justify-content: center;
221
+ flex-direction: column;
222
+ }
223
+ .pulling i {
224
+ /*
225
+ font-size: 20px;
226
+ */
227
+ }
228
+ .pulling .loading {
229
+ display: flex;
230
+ flex-direction: row;
231
+ align-items: center;
232
+ gap: 5px;
233
+ }
210
234
  </style>
211
235
  <script src="/hotkeys.min.js"></script>
212
236
  <script src="/sweetalert2.js"></script>
@@ -215,6 +239,16 @@ body.dark .btn {
215
239
  <script src="/nav.js"></script>
216
240
  </head>
217
241
  <body class='<%=theme%>' data-agent="<%=agent%>">
242
+ <header>
243
+ <h1>Build</h1>
244
+ <a class='btn' href="https://github.com/pinokiocomputer/code/issues" target="_blank"><i class="fa-solid fa-up-right-from-square"></i> Request a tool</a>
245
+ <a class='btn' id='git-pull'><i class="fa-solid fa-rotate"></i> Check for new tools</a>
246
+ <div class='pulling hidden'>
247
+ <div class='loading'>
248
+ <i class="fa-solid fa-circle-notch fa-spin"></i> refreshing...
249
+ </div>
250
+ </div>
251
+ </header>
218
252
  <main>
219
253
  <% dynamic.forEach((item, index) => { %>
220
254
  <% if (item.menu) { %>
@@ -279,6 +313,24 @@ setTimeout(() => {
279
313
  location.href = location.href
280
314
  }, 2000)
281
315
  <% } %>
316
+ document.querySelector("#git-pull").addEventListener("click", (e) => {
317
+ e.preventDefault()
318
+ e.stopPropagation()
319
+ document.querySelector(".pulling").classList.remove("hidden")
320
+ document.querySelector("#git-pull").classList.add("hidden")
321
+ fetch("/plugin/update", {
322
+ method: "POST"
323
+ }).then((res) => {
324
+ return res.json()
325
+ }).then((res) => {
326
+ if (res.success) {
327
+ location.href = location.href
328
+ } else if(res.error) {
329
+ document.querySelector("#git-pull").classList.remove("hidden")
330
+ alert(res.error)
331
+ }
332
+ })
333
+ })
282
334
  </script>
283
335
  </body>
284
336
  </html>
@@ -99,7 +99,6 @@ h2 {
99
99
  h1 {
100
100
  letter-spacing: 0px;
101
101
  font-size:40px;
102
- text-transform: uppercase;
103
102
  padding-bottom: 20px;
104
103
  }
105
104
 
@@ -194,7 +193,7 @@ body.dark .tab-nav {
194
193
  flex-direction: column;
195
194
  width: 220px !important;
196
195
  gap: 5px;
197
- padding: 20px;
196
+ padding: 15px 20px;
198
197
  background: none;
199
198
  border: none;
200
199
  cursor: pointer;
@@ -235,8 +234,8 @@ body.dark .tab-button:hover {
235
234
  .tab-button.active {
236
235
  color: #000;
237
236
  background: rgba(0,0,100,0.04);
238
- border-top-left-radius: 20px;
239
- border-bottom-left-radius: 20px;
237
+ border-top-left-radius: 50px;
238
+ border-bottom-left-radius: 50px;
240
239
  /*
241
240
  background: rgba(0,0,0,0.02);
242
241
  */
@@ -251,6 +250,10 @@ body.dark .tab-button.active {
251
250
  display: flex;
252
251
  align-items: center;
253
252
  }
253
+ .row i {
254
+ font-size: 20px;
255
+ padding-right: 15px;
256
+ }
254
257
 
255
258
  .tab-content {
256
259
  display: none;
@@ -404,7 +407,7 @@ body.dark textarea, body.dark input[type="url"], body.dark input[type="text"] {
404
407
  textarea, input[type="url"], input[type="text"] {
405
408
  width: 100%;
406
409
  padding: 10px;
407
- border: 1px solid rgba(0,0,0,0.1);
410
+ border: 2px solid rgba(0,0,0,0.1);
408
411
  font-family: inherit;
409
412
  background: white;
410
413
  }
@@ -1153,31 +1156,42 @@ body.dark .bubble:before {
1153
1156
  .ai-tab:hover {
1154
1157
  color: royalblue;
1155
1158
  }
1159
+ body.dark .ai-tab {
1160
+ color: silver;
1161
+ }
1156
1162
  .ai-tab {
1163
+ color: gray;
1157
1164
  cursor: pointer;
1158
- color: silver;
1159
1165
  padding: 10px 20px;
1160
1166
  font-size: 14px;
1161
1167
  width: 200px;
1162
1168
  }
1163
- .ai-tab.selected {
1164
- color: white;
1169
+ body.dark .ai-tab.selected {
1165
1170
  background: rgba(0,0,0,0.1);
1171
+ color: white;
1172
+ }
1173
+ .ai-tab.selected {
1174
+ color: black;
1175
+ background: white;
1166
1176
  border-top-left-radius: 20px;
1167
1177
  border-bottom-left-radius: 20px;
1168
1178
  font-weight: bold;
1169
1179
  }
1180
+ body.dark .ai-tab-content.selected {
1181
+ background: rgba(0,0,0,0.1);
1182
+ }
1170
1183
  .ai-tab-content.selected {
1171
1184
  display: flex;
1172
1185
  flex-direction: column;
1173
1186
  gap: 10px;
1174
- background: rgba(0,0,0,0.1);
1187
+ background: white;
1175
1188
  }
1176
1189
  .ai-tab-content .ai-input {
1177
1190
  background: white !important;
1178
1191
  color: black !important;
1179
1192
  }
1180
1193
  .ai-tab-content {
1194
+ min-height: 300px;
1181
1195
  border-top-right-radius: 20px;
1182
1196
  border-bottom-right-radius: 20px;
1183
1197
  display: none;
@@ -1188,12 +1202,19 @@ body.dark .bubble:before {
1188
1202
  }
1189
1203
  .ai-container h1 {
1190
1204
  padding: 0;
1205
+ font-size: 30px;
1206
+ /*
1207
+ font-weight: lighter;
1208
+ text-align: center;
1209
+ */
1191
1210
  font-weight: bold;
1192
- font-size: 25px;
1211
+ letter-spacing: -1px;
1193
1212
  }
1194
1213
  .md-desc {
1214
+ /*
1195
1215
  padding-left: 10px;
1196
1216
  border-left: 10px solid white;
1217
+ */
1197
1218
  }
1198
1219
 
1199
1220
 
@@ -1335,31 +1356,39 @@ body.dark .ace-editor {
1335
1356
  <div class="tab-nav">
1336
1357
  <button type="button" class="tab-button active" data-tab="launcher">
1337
1358
  <div class='row'>
1338
- <i class="fa-solid fa-cloud-arrow-down" style="margin-right: 5px;"></i>
1339
- <h5>Git Launcher</h5>
1359
+ <i class="fa-solid fa-cloud-arrow-down"></i>
1360
+ <div>
1361
+ <h5>Git Launcher</h5>
1362
+ <div>Launch any git-based open source project</div>
1363
+ </div>
1340
1364
  </div>
1341
- <div class='row'>Launch any git-based open source project</div>
1342
1365
  </button>
1343
1366
  <button type="button" class="tab-button" data-tab="cli">
1344
1367
  <div class='row'>
1345
- <i class="fa-solid fa-terminal" style="margin-right: 5px;"></i>
1346
- <h5>CLI App Launcher</h5>
1368
+ <i class="fa-solid fa-terminal"></i>
1369
+ <div>
1370
+ <h5>CLI App Launcher</h5>
1371
+ <div>Run any Terminal app in the browser.</div>
1372
+ </div>
1347
1373
  </div>
1348
- <div class='row'>Run any Terminal app in the browser.</div>
1349
1374
  </button>
1350
1375
  <button type="button" class="tab-button" data-tab="project">
1351
1376
  <div class='row'>
1352
- <i class="fa-regular fa-star" style="margin-right: 5px;"></i>
1353
- <h5>Empty Launcher</h5>
1377
+ <i class="fa-regular fa-pen-to-square"></i>
1378
+ <div>
1379
+ <h5>Empty Launcher</h5>
1380
+ <div>Start a new project with a built-in 1-click launcher.</div>
1381
+ </div>
1354
1382
  </div>
1355
- <div class='row'>Start a new project with a built-in 1-click launcher.</div>
1356
1383
  </button>
1357
1384
  <button type="button" class="tab-button" data-tab="quickcreate">
1358
1385
  <div class='row'>
1359
- <i class="fa-solid fa-robot" style="margin-right: 5px;"></i>
1360
- <h5>AI Engineer</h5>
1386
+ <i class="fa-solid fa-robot"></i>
1387
+ <div>
1388
+ <h5>AI Engineer</h5>
1389
+ <div>Let AI build a launcher for anything.</div>
1390
+ </div>
1361
1391
  </div>
1362
- <div class='row'>Let AI build a launcher for anything.</div>
1363
1392
  </button>
1364
1393
  </div>
1365
1394
 
@@ -1604,13 +1633,15 @@ body.dark .ace-editor {
1604
1633
  </div>
1605
1634
  <div class='ai-container'>
1606
1635
  <% ai.forEach((item, i) => { %>
1607
- <div class='ai-tab-content <%=i===0 ? "selected" : ""%>' data-title="<%=item.title%>">
1636
+ <div data-meta="<%=JSON.stringify(item.data)%>" class='ai-tab-content <%=i===0 ? "selected" : ""%>' data-title="<%=item.title%>">
1608
1637
  <h1><%=item.title%></h1>
1609
1638
  <div class='md-desc'><%=item.description%></div>
1610
1639
  <% Object.keys(item.meta).forEach((key) => { %>
1611
- <input class='ai-input' type='text' placeholder='<%=item.meta[key]%>' name='<%=key%>'>
1640
+ <% if (!key.startsWith(".")) { %>
1641
+ <input class='ai-input' type='text' placeholder='<%=item.meta[key]%>' name='<%=key%>'>
1642
+ <% } %>
1612
1643
  <% }) %>
1613
- <textarea><%=item.content%></textarea>
1644
+ <textarea placeholder="<%=item.description%>"><%=item.content%></textarea>
1614
1645
  <pre class='hidden'><%=item.content%></pre>
1615
1646
  </div>
1616
1647
  <% }) %>
@@ -1657,16 +1688,18 @@ document.addEventListener('DOMContentLoaded', function() {
1657
1688
  initializeTabs();
1658
1689
 
1659
1690
  document.querySelector(".ai-tabs").addEventListener("click", (e) => {
1660
- document.querySelectorAll(".ai-tab").forEach((el) => {
1661
- el.classList.remove('selected')
1662
- })
1663
- e.target.classList.add("selected")
1664
- document.querySelectorAll(`.ai-tab-content`).forEach((el) => {
1665
- el.classList.remove("selected")
1666
- })
1667
- let title = e.target.getAttribute("data-title")
1668
- document.querySelector(`.ai-tab-content[data-title="${title}"]`).classList.add('selected')
1669
- resizeAITextarea()
1691
+ if (e.target.classList.contains("ai-tab")) {
1692
+ document.querySelectorAll(".ai-tab").forEach((el) => {
1693
+ el.classList.remove('selected')
1694
+ })
1695
+ e.target.classList.add("selected")
1696
+ document.querySelectorAll(`.ai-tab-content`).forEach((el) => {
1697
+ el.classList.remove("selected")
1698
+ })
1699
+ let title = e.target.getAttribute("data-title")
1700
+ document.querySelector(`.ai-tab-content[data-title="${title}"]`).classList.add('selected')
1701
+ resizeAITextarea()
1702
+ }
1670
1703
  })
1671
1704
  document.querySelectorAll(".ai-tab-content").forEach((tab) => {
1672
1705
  tab.addEventListener("input", (e) => {
@@ -1685,6 +1718,7 @@ document.addEventListener('DOMContentLoaded', function() {
1685
1718
  }
1686
1719
  textarea.value = md
1687
1720
  document.querySelector("#aiPrompt").value = md
1721
+ console.log("MD", md)
1688
1722
  }
1689
1723
  })
1690
1724
  })
@@ -2134,6 +2168,17 @@ function validateForm() {
2134
2168
 
2135
2169
  function handleSubmit(event) {
2136
2170
  event.preventDefault();
2171
+
2172
+ let aiTab = document.querySelector(".ai-tab-content.selected textarea")
2173
+ let aiMeta = null
2174
+ if (aiTab && aiTab.value) {
2175
+ document.querySelector("#aiPrompt").value = aiTab.value
2176
+ let ai_meta_str = aiTab.closest(".ai-tab-content").getAttribute("data-meta")
2177
+ aiMeta = JSON.parse(ai_meta_str)
2178
+ }
2179
+ console.log({ aiMeta })
2180
+
2181
+
2137
2182
 
2138
2183
  if (!validateForm()) {
2139
2184
  return;
@@ -2217,7 +2262,8 @@ function handleSubmit(event) {
2217
2262
  docType: formData.get('docType'),
2218
2263
  localDocPath: formData.get('localDocPath'),
2219
2264
  remoteDocUrl: formData.get('remoteDocUrl'),
2220
- aiPrompt: aiPromptText
2265
+ aiPrompt: aiPromptText,
2266
+ aiMeta,
2221
2267
  };
2222
2268
 
2223
2269
  displayResults(config);
@@ -269,7 +269,7 @@ document.addEventListener("DOMContentLoaded", async () => {
269
269
  //term.write("\r\n" + packet.data + "\r\n")
270
270
  ModalInput({
271
271
  title: "Error",
272
- type: "moddal",
272
+ type: "modal",
273
273
  description: packet.data
274
274
  })
275
275
  } else if (packet.type === "notify3") {
@@ -285,6 +285,12 @@ document.addEventListener("DOMContentLoaded", async () => {
285
285
  document.querySelector("#status-screen").innerHTML = packet.data.html
286
286
  let audio = new Audio("/pop.mp3")
287
287
  audio.play()
288
+ ModalInput({
289
+ title: "Notice",
290
+ type: "modal",
291
+ description: packet.data.html,
292
+ confirm: "OK",
293
+ })
288
294
  }
289
295
  } else if (packet.type === "notify2") {
290
296
  console.log("HTML", packet.data)
@@ -360,6 +360,14 @@ body.dark .net {
360
360
  display: block;
361
361
  background: none;
362
362
  }
363
+ .placeholder-icon {
364
+ font-size: 40px;
365
+ width: 50px;
366
+ height: 50px;
367
+ display: flex;
368
+ justify-content: center;
369
+ align-items: center;
370
+ }
363
371
  @media only screen and (max-width: 480px) {
364
372
  .btn2 {
365
373
  padding: 5px;
@@ -451,197 +459,118 @@ body.dark .net {
451
459
  <% } %>
452
460
  </aside>
453
461
  <div class='container'>
454
- <form class='search'>
455
- <!--
456
- <div class='app-btns'>
457
- <a class='btn create-new' href="/init"><i class="fa-solid fa-plus"></i> Build</a>
458
- <a class='btn' id='explore' href="/?mode=explore"><i class="fa-solid fa-magnifying-glass"></i> Discover</a>
462
+ <form class='search'>
463
+ <!--
464
+ <div class='app-btns'>
465
+ <a class='btn create-new' href="/init"><i class="fa-solid fa-plus"></i> Build</a>
466
+ <a class='btn' id='explore' href="/?mode=explore"><i class="fa-solid fa-magnifying-glass"></i> Discover</a>
467
+ </div>
468
+ -->
469
+ <input type='search' class="flexible" placeholder='Search apps'>
470
+ </form>
471
+ <div class='running-apps'>
472
+ <% if (current_host === host) { %>
473
+ <div class='section-header'>
474
+ <h3>
475
+ <div class='blank'></div>
476
+ <div class='col'>
477
+ <div class='grid-3'>
478
+ <div class='section'>
479
+ <h2><i class='fas fa-laptop-code'></i> Local</h2>
480
+ <div>accessible from this machine</div>
481
+ </div>
482
+ <div class='section'>
483
+ <h2><i class="fa-solid fa-wifi"></i> Network</h2><div>accessible from any machine on the local network</div>
484
+ </div>
485
+ <div class='section'>
486
+ <h2><i class="fa-solid fa-podcast"></i> Peer</h2><div>accessible from any pinokio peer on the local network <a class='explain' data-type='peer'>How to start a peer</a></div>
487
+ </div>
488
+ </div>
489
+ </div>
490
+ </h3>
459
491
  </div>
460
- -->
461
- <input type='search' class="flexible" placeholder='Search apps'>
462
- </form>
463
- <div class='running-apps'>
464
- <% if (current_host === host) { %>
465
- <div class='section-header'>
492
+ <% processes.forEach((item, index) => { %>
493
+ <div class='line align-top' data-index="<%=index%>" data-name="<%=item.name%>" data-title="<%=item.name%>" data-description="<%=item.internal_router.join(' ')%> <%=item.port%>">
466
494
  <h3>
467
- <div class='blank'></div>
495
+ <div class='item-icon'>
496
+ <% if (favicons[item.external_ip]) { %>
497
+ <img src="<%=favicons[item.external_ip]%>">
498
+ <% } else { %>
499
+ <div class='placeholder-icon'>
500
+ <i class="fa-solid fa-database"></i>
501
+ </div>
502
+ <!--
503
+ <img src="/pinokio-black.png">
504
+ -->
505
+ <% } %>
506
+ </div>
468
507
  <div class='col'>
508
+ <div class='title'><i class="fa-solid fa-circle"></i><span><%=titles[item.ip] || item.name%></span></div>
469
509
  <div class='grid-3'>
470
510
  <div class='section'>
471
- <h2><i class='fas fa-laptop-code'></i> Local</h2>
472
- <div>accessible from this machine</div>
511
+ <% item.internal_router.forEach((domain) => { %>
512
+ <a class='net' target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
513
+ <% }) %>
514
+ <a class='net' target="_blank" href="http://localhost:<%=item.port%>">http://localhost:<%=item.port%></a>
473
515
  </div>
474
516
  <div class='section'>
475
- <h2><i class="fa-solid fa-wifi"></i> Network</h2><div>accessible from any machine on the local network</div>
517
+ <% if (item.external_ip) { %>
518
+ <a class='net' target="_blank" href="http://<%=item.external_ip%>">http://<%=item.external_ip%></a>
519
+ <% } %>
476
520
  </div>
477
521
  <div class='section'>
478
- <h2><i class="fa-solid fa-podcast"></i> Peer</h2><div>accessible from any pinokio peer on the local network <a class='explain' data-type='peer'>How to start a peer</a></div>
479
- </div>
480
- </div>
481
- </div>
482
- </h3>
483
- </div>
484
- <% processes.forEach((item, index) => { %>
485
- <div class='line align-top' data-index="<%=index%>" data-name="<%=item.name%>" data-title="<%=item.name%>" data-description="<%=item.internal_router.join(' ')%> <%=item.port%>">
486
- <h3>
487
- <div class='item-icon'>
488
- <% if (favicons[item.external_ip]) { %>
489
- <img src="<%=favicons[item.external_ip]%>">
490
- <% } else { %>
491
- <img src="/pinokio-black.png">
492
- <% } %>
493
- </div>
494
- <div class='col'>
495
- <div class='title'><i class="fa-solid fa-circle"></i><span><%=titles[item.ip] || item.name%></span></div>
496
- <div class='grid-3'>
497
- <div class='section'>
498
- <% item.internal_router.forEach((domain) => { %>
499
- <a class='net' target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
500
- <% }) %>
501
- <a class='net' target="_blank" href="http://localhost:<%=item.port%>">http://localhost:<%=item.port%></a>
502
- </div>
503
- <div class='section'>
504
- <% if (item.external_ip) { %>
505
- <a class='net' target="_blank" href="http://<%=item.external_ip%>">http://<%=item.external_ip%></a>
506
- <% } %>
507
- </div>
508
- <div class='section'>
509
- <% item.external_router.forEach((domain) => { %>
510
- <a class='net' target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
511
- <% }) %>
512
- </div>
522
+ <% item.external_router.forEach((domain) => { %>
523
+ <a class='net' target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
524
+ <% }) %>
513
525
  </div>
514
526
  </div>
515
527
  </div>
516
- </h3>
517
- <% }) %>
518
- <% } else { %>
519
- <div class='section-header'>
520
- <h3>
521
- <div class='blank'></div>
522
- <div class='col'>
523
- <div class='grid-1'>
524
- <div class='section'>
525
- <h2>Endpoints</h2><div>accessible through peer network</div>
526
- </div>
528
+ </div>
529
+ </h3>
530
+ <% }) %>
531
+ <% } else { %>
532
+ <div class='section-header'>
533
+ <h3>
534
+ <div class='blank'></div>
535
+ <div class='col'>
536
+ <div class='grid-1'>
537
+ <div class='section'>
538
+ <h2>Endpoints</h2><div>accessible through peer network</div>
527
539
  </div>
528
540
  </div>
529
- </h3>
530
- </div>
531
- <% processes.forEach((item, index) => { %>
532
- <div class='line align-top' data-index="<%=index%>" data-name="<%=item.name%>" data-title="<%=item.name%>" data-description="<%=item.external_router.join(' ')%> <%=item.external_ip%>">
533
- <h3>
534
- <div class='item-icon'>
535
- <% if (favicons[item.ip]) { %>
536
- <img src="<%=favicons[item.ip]%>">
537
- <% } else { %>
538
- <img src="/pinokio-black.png">
539
- <% } %>
540
- </div>
541
- <div class='col'>
542
- <div class='title'><i class="fa-solid fa-circle"></i><span><%=titles[item.ip] || item.name%></span></div>
543
- <div class='grid-1'>
544
- <div class='section'>
545
- <% if (item.external_ip) { %>
546
- <a class='net' target="_blank" href="http://<%=item.external_ip%>">http://<%=item.external_ip%></a>
547
- <% } %>
548
- <% item.external_router.forEach((domain) => { %>
549
- <a class='net' target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
550
- <% }) %>
551
- </div>
552
- </div>
553
- </div>
554
- </h3>
555
541
  </div>
556
- <% }) %>
557
- <% } %>
558
- <% running.forEach((item) => { %>
559
- <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'>
542
+ </h3>
543
+ </div>
544
+ <% processes.forEach((item, index) => { %>
545
+ <div class='line align-top' data-index="<%=index%>" data-name="<%=item.name%>" data-title="<%=item.name%>" data-description="<%=item.external_router.join(' ')%> <%=item.external_ip%>">
560
546
  <h3>
561
547
  <div class='item-icon'>
562
- <% if (item.icon) { %>
563
- <img src="<%=item.icon%>">
548
+ <% if (favicons[item.ip]) { %>
549
+ <img src="<%=favicons[item.ip]%>">
564
550
  <% } else { %>
565
- <% if (theme === 'dark') { %>
566
- <img src="/pinokio-white.png">
567
- <% } else { %>
568
- <img src="/pinokio-black.png">
569
- <% } %>
551
+ <div class='placeholder-icon'>
552
+ <i class="fa-solid fa-database"></i>
553
+ </div>
570
554
  <% } %>
571
555
  </div>
572
556
  <div class='col'>
573
- <div class='uri'><%=item.filepath%></div>
574
- <div class='title'><%=item.name%></div>
575
- <div class='description'><%=item.description%></div>
576
- <div class='menu-btns'>
577
- <button class='btn browse' data-src="<%=item.browser_url%>/dev">
578
- <i class='fa-solid fa-code'></i> Dev
579
- </button>
580
- <button class='btn open-menu'>
581
- <i class="fa-solid fa-bars"></i><span> Menu</span>
582
- </button>
583
- <div class='context-menu collapsed'>
584
- <div class='context-menu-wrapper'>
585
- <button class='btn' data-filepath="<%=item.filepath%>">
586
- <i class="fa-solid fa-folder-open"></i> Open</button>
587
- </button>
588
- <button class='btn copy-menu' data-src="<%=item.browser_url%>/dev">
589
- <i class='fa-solid fa-copy'></i> Copy
590
- </button>
591
- <button class='btn move-menu' data-src="<%=item.browser_url%>/dev" data-disable="To move the folder, the app should not be running.">
592
- <i class="fa-solid fa-right-to-bracket"></i> Move
593
- </button>
594
- <button class='btn edit-menu' data-src="<%=item.browser_url%>/dev">
595
- <i class='fa-solid fa-pen-to-square'></i> Edit
596
- </button>
597
- <button class='btn del' data-src="<%=item.url%>" data-disable="To delete the folder, the app should not be running.">
598
- <i class="fa-solid fa-trash-can"></i> Delete
599
- </button>
600
- </div>
601
- </div>
602
- <% if (item.running_scripts) { %>
603
- <% item.running_scripts.forEach((s) => { %>
604
- <% if (s.id) { %>
605
- <button class='btn shutdown' data-id="<%=s.id%>" data-type="<%=s.type ? s.type : ''%>">
606
- <i class="fa-solid fa-stop"></i> Stop <%=s.name%>&nbsp;
607
- <i class='fa-solid fa-spin fa-circle-notch'></i>
608
- </button>
609
- <% } else { %>
610
- <button class='btn shutdown' data-src="<%=s.path%>">
611
- <i class="fa-solid fa-stop"></i> Stop <%=s.name%>&nbsp;
612
- <i class='fa-solid fa-spin fa-circle-notch'></i>
613
- </button>
614
- <% } %>
615
- <% }) %>
616
- <% } %>
617
- </div>
618
- <% if (item.shortcuts && item.shortcuts.length > 0) { %>
619
- <div class='btns'>
620
- <% item.shortcuts.forEach((btn) => { %>
621
- <% if (btn.btn) { %>
622
- <button data-action="<%=btn.action ? JSON.stringify(btn.action) : ''%>" class='btn menu-btn'><%-btn.btn%></button>
623
- <% } %>
557
+ <div class='title'><i class="fa-solid fa-circle"></i><span><%=titles[item.ip] || item.name%></span></div>
558
+ <div class='grid-1'>
559
+ <div class='section'>
560
+ <% if (item.external_ip) { %>
561
+ <a class='net' target="_blank" href="http://<%=item.external_ip%>">http://<%=item.external_ip%></a>
562
+ <% } %>
563
+ <% item.external_router.forEach((domain) => { %>
564
+ <a class='net' target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
624
565
  <% }) %>
625
566
  </div>
626
- <% } %>
627
- </div>
628
- <!--
629
- <div class='spinner'>
630
- <i class="fa-solid fa-chevron-right"></i>
567
+ </div>
631
568
  </div>
632
- -->
633
569
  </h3>
634
- </a>
570
+ </div>
635
571
  <% }) %>
636
- </div>
637
- <% if (list.length === 0) { %>
638
- <div class='placeholder'>
639
- <h1>Welcome.</h1>
640
- <br>
641
- <div>Get started by installing some Pinokio scripts.</div>
642
- <a href="/?mode=explore" class='btn'><i class="fa-solid fa-globe"></i> Visit Discover Page</a>
643
- </div>
644
- <% } %>
572
+ <% } %>
573
+ </div>
645
574
  </div>
646
575
  </main>
647
576
  <script>