pinokiod 3.9.0 → 3.9.2

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.
Files changed (118) hide show
  1. package/kernel/api/filepicker/index.js +59 -0
  2. package/kernel/api/fs/index.js +6 -4
  3. package/kernel/api/index.js +123 -37
  4. package/kernel/api/input/index.js +2 -0
  5. package/kernel/api/web/index.js +6 -0
  6. package/kernel/bin/caddy.js +127 -0
  7. package/kernel/bin/cloudflared.js +1 -0
  8. package/kernel/bin/conda.js +10 -2
  9. package/kernel/bin/cuda.js +0 -16
  10. package/kernel/bin/ffmpeg.js +4 -6
  11. package/kernel/bin/git.js +55 -29
  12. package/kernel/bin/gxx.js +8 -6
  13. package/kernel/bin/huggingface.js +4 -5
  14. package/kernel/bin/index.js +347 -88
  15. package/kernel/bin/node.js +13 -6
  16. package/kernel/bin/py.js +1 -1
  17. package/kernel/bin/setup.js +146 -0
  18. package/kernel/bin/uv.js +4 -5
  19. package/kernel/bin/zip.js +7 -8
  20. package/kernel/connect/index.js +25 -0
  21. package/kernel/connect/providers/github/README.md +11 -0
  22. package/kernel/connect/providers/x/README.md +96 -0
  23. package/kernel/connect/providers/x/index.js +152 -0
  24. package/kernel/environment.js +50 -1
  25. package/kernel/index.js +152 -32
  26. package/kernel/info.js +4 -2
  27. package/kernel/kv.js +38 -0
  28. package/kernel/loader.js +13 -3
  29. package/kernel/peer.js +161 -0
  30. package/kernel/procs.js +116 -0
  31. package/kernel/prototype.js +62 -0
  32. package/kernel/router/common.js +42 -0
  33. package/kernel/router/connector.js +81 -0
  34. package/kernel/router/index.js +235 -0
  35. package/kernel/router/localhost_home_router.js +84 -0
  36. package/kernel/router/localhost_port_router.js +15 -0
  37. package/kernel/router/localhost_variable_router.js +37 -0
  38. package/kernel/router/peer_home_router.js +15 -0
  39. package/kernel/router/peer_peer_router.js +26 -0
  40. package/kernel/router/peer_port_router.js +45 -0
  41. package/kernel/router/peer_variable_router.js +46 -0
  42. package/kernel/router/processor.js +31 -0
  43. package/kernel/shell.js +141 -60
  44. package/kernel/shells.js +32 -17
  45. package/kernel/store.js +58 -0
  46. package/kernel/sysinfo.js +0 -1
  47. package/kernel/util.js +143 -36
  48. package/package.json +4 -1
  49. package/pipe/index.js +0 -2
  50. package/script/index.js +12 -0
  51. package/server/index.js +1473 -553
  52. package/server/public/Socket.js +5 -1
  53. package/server/public/SourceCodePro-Regular.ttf +0 -0
  54. package/server/public/SpaceMono-Bold.ttf +0 -0
  55. package/server/public/SpaceMono-BoldItalic.ttf +0 -0
  56. package/server/public/SpaceMono-Italic.ttf +0 -0
  57. package/server/public/SpaceMono-Regular.ttf +0 -0
  58. package/server/public/commander.js +40 -0
  59. package/server/public/common.js +60 -0
  60. package/server/public/dropzone-min.js +2 -0
  61. package/server/public/dropzone.css +1 -0
  62. package/server/public/filepond-plugin-file-validate-type.min.js +9 -0
  63. package/server/public/filepond-plugin-image-crop.min.js +9 -0
  64. package/server/public/filepond-plugin-image-edit.min.css +8 -0
  65. package/server/public/filepond-plugin-image-edit.min.js +9 -0
  66. package/server/public/filepond-plugin-image-exif-orientation.min.js +9 -0
  67. package/server/public/filepond-plugin-image-preview.min.css +8 -0
  68. package/server/public/filepond-plugin-image-preview.min.js +9 -0
  69. package/server/public/filepond-plugin-image-resize.min.js +9 -0
  70. package/server/public/filepond-plugin-image-transform.min.js +9 -0
  71. package/server/public/filepond.min.css +8 -0
  72. package/server/public/filepond.min.js +9 -0
  73. package/server/public/fscreator.js +174 -0
  74. package/server/public/fseditor.js +212 -0
  75. package/server/public/github.png +0 -0
  76. package/server/public/highlight-js.js +81 -0
  77. package/server/public/highlight.css +9 -0
  78. package/server/public/highlight.js +1244 -0
  79. package/server/public/install.js +17 -20
  80. package/server/public/modalinput.js +105 -9
  81. package/server/public/opener.js +3 -1
  82. package/server/public/pinokio-black.png +0 -0
  83. package/server/public/pinokio-black2.png +0 -0
  84. package/server/public/redoc.standalone.js +1832 -0
  85. package/server/public/style.css +211 -17
  86. package/server/public/swagger-ui-bundle.js +2 -0
  87. package/server/public/swagger-ui.css +3 -0
  88. package/server/public/x.js +63 -0
  89. package/server/socket.js +136 -39
  90. package/server/views/404.ejs +0 -1
  91. package/server/views/app.ejs +356 -90
  92. package/server/views/bootstrap.ejs +22 -19
  93. package/server/views/connect/x.ejs +324 -0
  94. package/server/views/connect.ejs +197 -0
  95. package/server/views/download.ejs +7 -1
  96. package/server/views/editor.ejs +68 -9
  97. package/server/views/explore.ejs +13 -10
  98. package/server/views/file_explorer.ejs +10 -37
  99. package/server/views/github.ejs +218 -0
  100. package/server/views/help.ejs +4 -3
  101. package/server/views/index.ejs +268 -118
  102. package/server/views/install.ejs +56 -29
  103. package/server/views/keys.ejs +276 -0
  104. package/server/views/network.ejs +889 -0
  105. package/server/views/partials/dynamic.ejs +9 -0
  106. package/server/views/partials/menu.ejs +7 -1
  107. package/server/views/prototype/index.ejs +311 -0
  108. package/server/views/prototype/show.ejs +383 -0
  109. package/server/views/redoc.ejs +18 -0
  110. package/server/views/required_env_editor.ejs +11 -2
  111. package/server/views/settings.ejs +38 -10
  112. package/server/views/setup.ejs +254 -0
  113. package/server/views/setup_home.ejs +192 -0
  114. package/server/views/shell.ejs +781 -0
  115. package/server/views/swaggerui.ejs +19 -0
  116. package/server/views/terminal.ejs +174 -42
  117. package/LICENSE +0 -7
  118. package/server/views/proxy.ejs +0 -405
@@ -95,9 +95,11 @@ td.key {
95
95
  .button:hover {
96
96
 
97
97
  }
98
+ /*
98
99
  #editor {
99
100
  background: var(--dark-bg);
100
101
  }
102
+ */
101
103
  header .runner {
102
104
  padding: 10px 0 0;
103
105
  }
@@ -113,6 +115,7 @@ body.frozen {
113
115
  }
114
116
  </style>
115
117
  <script>
118
+ let shell_id
116
119
  document.addEventListener("DOMContentLoaded", async () => {
117
120
  <% if (error) { %>
118
121
  document.querySelector(".requirements .content").innerHTML = '<div class="loading"><i class="fa-solid fa-circle-exclamation"></i> <%=error%></div>'
@@ -152,13 +155,14 @@ document.addEventListener("DOMContentLoaded", async () => {
152
155
  <% } %>
153
156
  <% if (!install_required) { %>
154
157
  let editor = ace.edit("editor");
155
- //editor.setTheme("ace/theme/tomorrow");
158
+ editor.setTheme("ace/theme/tomorrow");
159
+ //editor.setTheme("ace/theme/github_light_default");
156
160
  //editor.setTheme("ace/theme/ambiance");
157
161
  //editor.setTheme("ace/theme/idle_fingers");
158
- editor.setTheme("ace/theme/nord_dark");
162
+ //editor.setTheme("ace/theme/nord_dark");
159
163
  //editor.setTheme("ace/theme/textmate");
160
164
  editor.setOptions({
161
- maxLines: Infinity, // set to a large number
165
+ // maxLines: Infinity, // set to a large number
162
166
  minLines: 1 // set to a small number
163
167
  });
164
168
  console.log("location.pathname", location.pathname)
@@ -329,10 +333,37 @@ document.addEventListener("DOMContentLoaded", async () => {
329
333
  document.querySelector(".run .play").classList.remove("hidden")
330
334
  document.querySelector(".run .stop").classList.add("hidden")
331
335
 
336
+ <% if (kill_message) { %>
337
+ n.Noty({
338
+ text: "<%-kill_message%>",
339
+ // timeout: 3000,
340
+ <% if (callback) { %>
341
+ callbacks: {
342
+ onClose: () => {
343
+ location.href = "<%=callback%>"
344
+ }
345
+ }
346
+ <% } %>
347
+ })
348
+ <% } else { %>
349
+ <% if (callback) { %>
350
+ location.href = "<%=callback%>"
351
+ <% } %>
352
+ <% } %>
353
+
332
354
  } else if (packet.type === 'connect') {
333
355
  // document.querySelector(".terminal-container").classList.remove("hidden")
334
- const message = "..........Connected!\r\n"
335
- this.term.write(message)
356
+ if (packet.data.id) {
357
+ shell_id = packet.data.id
358
+ }
359
+ if (packet.data) {
360
+ if (packet.data.shell) {
361
+ shell_id = packet.data.shell
362
+ }
363
+ if (packet.data.state) {
364
+ this.write(packet.data.state)
365
+ }
366
+ }
336
367
  /*
337
368
  for(let i=0; i<message.length; i++) {
338
369
  await new Promise((r, reject) => {
@@ -391,6 +422,25 @@ document.addEventListener("DOMContentLoaded", async () => {
391
422
  */
392
423
  } else if (packet.type === "tab.open") {
393
424
  // refreshParent(packet)
425
+ } else if (packet.type === "web.open") {
426
+ /*
427
+ {
428
+ "method": "web.open",
429
+ "params": {
430
+ "uri",
431
+ "target": "_self (default)"|"_blank"|"_parent"|"_top",
432
+ "features"
433
+ }
434
+ }
435
+ */
436
+
437
+ refreshParent()
438
+ let params = packet.data
439
+ window.open(
440
+ params.uri,
441
+ (params.target || "_self"),
442
+ params.features
443
+ )
394
444
  } else if (packet.type === "browser.open") {
395
445
  /*
396
446
  {
@@ -578,14 +628,23 @@ document.addEventListener("DOMContentLoaded", async () => {
578
628
  // })
579
629
  // }
580
630
 
581
- await this.createTerm()
631
+ <% if (theme === "dark") { %>
632
+ await this.createTerm(xtermTheme.FrontEndDelight)
633
+ <% } else { %>
634
+ await this.createTerm(xtermTheme.Tomorrow)
635
+ <% } %>
582
636
  await this.start(mode)
583
637
  }
584
- async createTerm () {
638
+ async createTerm (_theme) {
585
639
  if (!this.term) {
640
+ const theme = Object.assign({ }, _theme, {
641
+ selectionBackground: "red",
642
+ selectionForeground: "white"
643
+ })
586
644
  let config = {
587
- fontSize: 12,
588
- theme: xtermTheme.FrontEndDelight
645
+ scrollback: 9999999,
646
+ fontSize: 14,
647
+ theme,
589
648
  }
590
649
  let res = await fetch("/xterm_config").then((res) => {
591
650
  return res.json()
@@ -120,20 +120,23 @@ body main iframe {
120
120
  <header class='navheader grabbable'>
121
121
  <h1>
122
122
  <a class='home' href="/"><i class="fa-solid fa-house"></i></a>
123
- <button class='btn2' id='back'><i class="fa-solid fa-chevron-left"></i></button>
124
- <button class='btn2' id='forward'><i class="fa-solid fa-chevron-right"></i></button>
125
- <% paths.forEach((path) => { %>
126
- <% if (path.action) { %>
127
- <a class='path nav-button' id="<%=path.id%>" onclick="<%=path.action%>"><%-path.name%></a>
128
- <% } else if (path.path) { %>
129
- <a class='path' href="<%=path.path%>"><%-path.name%></a>
130
- <% } %>
131
- <% }) %>
123
+ <button class='btn2' id='back'><div><i class="fa-solid fa-chevron-left"></i></div><div>Prev</div></button>
124
+ <button class='btn2' id='forward'><div><i class="fa-solid fa-chevron-right"></i></div><div>Next</div></button>
125
+ <a class='btn2 create-new' id='create-new-folder'><div><i class='fa-solid fa-plus'></i></div><div>New</div></a>
126
+ <a class='btn2' id='explore' href="/?mode=explore"><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
127
+ <a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Network</div></a>
128
+ <a href="/connect" class='btn2'><div><i class="fa-solid fa-circle-user"></i></div><div>Connect</div></a>
132
129
  <div class='flexible'></div>
133
130
  <div class='nav-btns'>
134
- <a class='btn2' id='explore' href="/?mode=explore"><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
135
131
  <a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
132
+ <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
133
+ <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>
136
134
  <a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
135
+ <% if (agent === "electron") { %>
136
+ <a href="/" target="_blank" class='btn2' features="browser"><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
137
+ <% } else { %>
138
+ <a href="/" target="_blank" class='btn2'><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
139
+ <% } %>
137
140
  <button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
138
141
  </div>
139
142
  <!--
@@ -3,7 +3,6 @@
3
3
  <title>Pinokio</title>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
6
- <link href="/xterm.min.css" rel="stylesheet" />
7
6
  <link href="/css/fontawesome.min.css" rel="stylesheet">
8
7
  <link href="/css/solid.min.css" rel="stylesheet">
9
8
  <link href="/css/regular.min.css" rel="stylesheet">
@@ -141,10 +140,6 @@ body.dark .browser-options-row {
141
140
  <script src="/sweetalert2.js"></script>
142
141
  <script src="/noty.js"></script>
143
142
  <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
143
  <script src="/Socket.js"></script>
149
144
  <script src="/install.js"></script>
150
145
  <script src="/common.js"></script>
@@ -158,7 +153,7 @@ body.dark .browser-options-row {
158
153
  <nav class='error-message'>
159
154
  <div><%=error%></div>
160
155
  <div class='flexible'></div>
161
- <a class='btn' target="_blank" href="<%=install%> Download</a>
156
+ <a class='btn' target="_blank" href="<%=install%>">Download</a>
162
157
  </nav>
163
158
  <% } %>
164
159
  <!--
@@ -191,7 +186,7 @@ body.dark .browser-options-row {
191
186
  <% if (agent === "electron") { %>
192
187
  <a class='btn2' data-filepath="<%=filepath%>"><div><i class="fa-regular fa-folder-open"></i></div><div>Files</div></a>
193
188
  <% } %>
194
- <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Debug</div></button>
189
+ <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
195
190
  <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
191
  <a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
197
192
  <button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
@@ -240,7 +235,7 @@ body.dark .browser-options-row {
240
235
  </div>
241
236
  <% } %>
242
237
  <div class='browser-options-row'>
243
- <a href="/proxy" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
238
+ <a href="/network" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
244
239
  <div class='flexible'>
245
240
  <h3><i class="fa-solid fa-wifi"></i> Local Sharing</h3>
246
241
  <div>Serve Pinokio, installed apps, and even external apps (example: Ollama) to any device on the same network.</div>
@@ -460,9 +455,15 @@ var term
460
455
  const n = new N()
461
456
  let socket = new Socket()
462
457
  const pull = async () => {
463
- if (!term) term = createTerm()
464
458
  socket.close()
465
459
  await new Promise((resolve, reject) => {
460
+ if (!term) {
461
+ <% if (theme === "dark") { %>
462
+ await createTerm(xtermTheme.FrontEndDelight)
463
+ <% } else { %>
464
+ await createTerm(xtermTheme.Tomorrow)
465
+ <% } %>
466
+ }
466
467
  let cwd
467
468
  let chunks = location.pathname.split("/").filter((x) => { return x })
468
469
  if (chunks.length > 0) {
@@ -1042,34 +1043,6 @@ if (document.querySelector("#cloudflare")) {
1042
1043
  })
1043
1044
  }
1044
1045
  <% } %>
1045
- if (document.querySelector("#back")) {
1046
- document.querySelector("#back").addEventListener("click", (e) => {
1047
- history.back()
1048
- })
1049
- }
1050
- if (document.querySelector("#forward")) {
1051
- document.querySelector("#forward").addEventListener("click", (e) => {
1052
- history.forward()
1053
- })
1054
- }
1055
- if (document.querySelector("#genlog")) {
1056
- document.querySelector("#genlog").addEventListener("click", (e) => {
1057
- e.preventDefault()
1058
- e.stopPropagation()
1059
- e.target.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
1060
- fetch("/pinokio/log", {
1061
- method: "post",
1062
- }).then((res) => {
1063
- console.log("RES", res)
1064
- let btn = document.querySelector("#genlog")
1065
- let btn2 = document.querySelector("#downloadlogs")
1066
- btn2.classList.remove("hidden")
1067
- btn.classList.add("hidden")
1068
- btn.innerHTML = '<i class="fa-solid fa-circle-check"></i> Generated!'
1069
- //btn.classList.add("hidden")
1070
- })
1071
- })
1072
- }
1073
1046
 
1074
1047
  </script>
1075
1048
  </body>
@@ -0,0 +1,218 @@
1
+ <html>
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
+ <link href="/xterm.min.css" rel="stylesheet" />
6
+ <link href="/css/fontawesome.min.css" rel="stylesheet">
7
+ <link href="/css/solid.min.css" rel="stylesheet">
8
+ <link href="/css/regular.min.css" rel="stylesheet">
9
+ <link href="/css/brands.min.css" rel="stylesheet">
10
+ <link href="/markdown.css" rel="stylesheet"/>
11
+ <link href="/noty.css" rel="stylesheet"/>
12
+ <link href="/style.css" rel="stylesheet"/>
13
+ <% if (agent === "electron") { %>
14
+ <link href="/electron.css" rel="stylesheet"/>
15
+ <% } %>
16
+ <style>
17
+ html {
18
+ scroll-behavior: smooth;
19
+ height: 100%;
20
+ overflow: hidden;
21
+ }
22
+ body {
23
+ height: 100%;
24
+ overflow: auto;
25
+ display: flex;
26
+ flex-direction: column;
27
+ }
28
+ .line2 {
29
+ display: flex;
30
+ align-items: center;
31
+ cursor: pointer;
32
+ background: rgba(0,0,100,0.04);
33
+ }
34
+ .line2 a {
35
+ text-decoration: none;
36
+ color: black;
37
+ }
38
+ .status {
39
+ padding: 10px;
40
+ margin: 10px;
41
+ border-radius: 10px;
42
+ }
43
+ .status.offline {
44
+ background: silver;
45
+ }
46
+ .status.online {
47
+ background: yellowgreen;
48
+ }
49
+ .switch {
50
+ padding: 10px;
51
+ margin: 10px 0;
52
+ }
53
+ .switch[data-online=true] {
54
+ color: yellowgreen;
55
+ }
56
+ .button {
57
+ padding: 10px;
58
+ }
59
+ .on, .off {
60
+ display: flex;
61
+ align-items: center;
62
+ }
63
+ .btn {
64
+ margin: 5px;
65
+ width: 100px;
66
+ text-align: center;
67
+ padding: 10px;
68
+ background: black;
69
+ color: white;
70
+ text-decoration: none;
71
+ font-weight: normal;
72
+ }
73
+ .item {
74
+ display: flex;
75
+ align-items: flex-start;
76
+ margin: 10px;
77
+ background: rgba(0,0,0,0.04);
78
+ }
79
+ .item img {
80
+ width: 100px;
81
+ }
82
+ .item .title {
83
+ text-decoration: none;
84
+ color: royalblue;
85
+ }
86
+ .item .col {
87
+ padding: 10px;
88
+ }
89
+ .item .col > * {
90
+ margin: 5px 0;
91
+ }
92
+ .item .stat {
93
+ color: rgba(0,0,0,0.8);
94
+ display: flex;
95
+ }
96
+ .item .stat > * {
97
+ margin-right: 15px;
98
+ }
99
+ .timestamp {
100
+ color: rgba(0,0,0,0.5);
101
+ }
102
+ main {
103
+ flex-grow: 1;
104
+ display: flex;
105
+ flex-direction: column;
106
+ }
107
+ .setup-items {
108
+ display: flex;
109
+ justify-content: center;
110
+ margin: 0 auto;
111
+ max-width: 800px;
112
+ width: 100%;
113
+ }
114
+ .head {
115
+ padding: 80px;
116
+ text-align: center;
117
+ }
118
+ .head .desc {
119
+ opacity: 0.7;
120
+ padding: 10px;
121
+ }
122
+ .head h3 {
123
+ font-size: 20px;
124
+ text-transform: uppercase;
125
+ margin: 0;
126
+ }
127
+ .head h3 i {
128
+ font-size: 80px;
129
+ }
130
+ body.dark .card {
131
+ color: white;
132
+ }
133
+ .card {
134
+ text-decoration: none;
135
+ width: 200px;
136
+ color: rgba(0,0,0,0.9);
137
+ text-align: center;
138
+ margin: 20px;
139
+ }
140
+ .card:hover {
141
+ color: royalblue !important;
142
+ }
143
+ .card .desc {
144
+ opacity: 0.7;
145
+ }
146
+ .card h3 {
147
+ font-size: 30px;
148
+ letter-spacing: -1px;
149
+ }
150
+ .card i {
151
+ font-size: 50px;
152
+ }
153
+ a {
154
+ color: royalblue;
155
+ }
156
+ body.dark hr {
157
+ background: rgba(255,255,255,0.05);
158
+ }
159
+ hr {
160
+ background: rgba(0,0,0,0.05);
161
+ height: 4px;
162
+ border: none;
163
+ margin: 40px 0;
164
+ }
165
+ #readme {
166
+ flex-grow: 1;
167
+ padding: 30px;
168
+ }
169
+ </style>
170
+ <script src="/hotkeys.min.js"></script>
171
+ <script src="/common.js"></script>
172
+ <script src="/opener.js"></script>
173
+ </head>
174
+ <body class='<%=theme%>'>
175
+ <header class='navheader grabbable'>
176
+ <h1>
177
+ <a class='home' href="/"><i class="fa-solid fa-house"></i></a>
178
+ <button class='btn2' id='back'><div><i class="fa-solid fa-chevron-left"></i></div><div>Prev</div></button>
179
+ <button class='btn2' id='forward'><div><i class="fa-solid fa-chevron-right"></i></div><div>Next</div></button>
180
+ <a class='btn2 create-new' id='create-new-folder'><div><i class='fa-solid fa-plus'></i></div><div>New</div></a>
181
+ <a class='btn2' id='explore' href="/?mode=explore"><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
182
+ <a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Network</div></a>
183
+ <a href="/connect" class='btn2'><div><i class="fa-solid fa-circle-user"></i></div><div>Connect</div></a>
184
+ <div class='flexible'></div>
185
+ <div class='nav-btns'>
186
+ <a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
187
+ <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
188
+ <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>
189
+ <a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
190
+ <% if (agent === "electron") { %>
191
+ <a href="/" target="_blank" class='btn2' features="browser"><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
192
+ <% } else { %>
193
+ <a href="/" target="_blank" class='btn2'><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
194
+ <% } %>
195
+ <button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
196
+ </div>
197
+ </h1>
198
+ </h1>
199
+ </header>
200
+ <main>
201
+ <div class='head'>
202
+ <h3><i class="fa-brands fa-github"></i><br><br>Connect with Github</h3>
203
+ </div>
204
+ <div class='setup-items'>
205
+ <% items.forEach((item) => { %>
206
+ <a class='card' href="<%=item.url%>">
207
+ <i class="<%=item.icon%>"></i>
208
+ <h3><%=item.title%></h3>
209
+ <div class='desc'><%=item.description%></div>
210
+ </a>
211
+ <% }) %>
212
+ </div>
213
+ <div class='setup-items'>
214
+ <div id='readme'><%-readme%></div>
215
+ </div>
216
+ </main>
217
+ </body>
218
+ </html>
@@ -255,11 +255,12 @@ body.dark .item .tile .badge {
255
255
  <header class='navheader grabbable'>
256
256
  <h1>
257
257
  <a class='home' href="/"><i class="fa-solid fa-house"></i></a>
258
- <button class='btn2' id='back'><i class="fa-solid fa-chevron-left"></i></button>
259
- <button class='btn2' id='forward'><i class="fa-solid fa-chevron-right"></i></button>
258
+ <button class='btn2' id='back'><div><i class="fa-solid fa-chevron-left"></i></div><div>Prev</div></button>
259
+ <button class='btn2' id='forward'><div><i class="fa-solid fa-chevron-right"></i></div><div>Next</div></button>
260
+ <a class='btn2 create-new' id='create-new-folder'><div><i class='fa-solid fa-plus'></i></div><div>New</div></a>
261
+ <a class='btn2' id='explore' href="/?mode=explore"><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
260
262
  <div class='flexible'></div>
261
263
  <div class='nav-btns'>
262
- <a class='btn2' id='explore' href="/?mode=explore"><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
263
264
  <a class='btn2' href="/?mode=help"><div><i class="fa-regular fa-face-smile"></i></div><div>Community</div></a>
264
265
  <a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
265
266
  <button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>