pinokiod 3.8.1 → 3.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/kernel/api/fs/index.js +6 -4
- package/kernel/api/index.js +102 -31
- package/kernel/bin/index.js +143 -4
- package/kernel/bin/node.js +9 -0
- package/kernel/index.js +32 -1
- package/kernel/info.js +1 -0
- package/kernel/prototype.js +47 -0
- package/kernel/shell.js +110 -54
- package/kernel/shells.js +16 -7
- package/kernel/store.js +58 -0
- package/kernel/util.js +106 -35
- package/package.json +1 -1
- package/script/index.js +12 -0
- package/server/index.js +466 -250
- package/server/public/SpaceMono-Bold.ttf +0 -0
- package/server/public/SpaceMono-BoldItalic.ttf +0 -0
- package/server/public/SpaceMono-Italic.ttf +0 -0
- package/server/public/SpaceMono-Regular.ttf +0 -0
- package/server/public/filepond-plugin-file-validate-type.min.js +9 -0
- package/server/public/filepond-plugin-image-crop.min.js +9 -0
- package/server/public/filepond-plugin-image-edit.min.css +8 -0
- package/server/public/filepond-plugin-image-edit.min.js +9 -0
- package/server/public/filepond-plugin-image-exif-orientation.min.js +9 -0
- package/server/public/filepond-plugin-image-preview.min.css +8 -0
- package/server/public/filepond-plugin-image-preview.min.js +9 -0
- package/server/public/filepond-plugin-image-resize.min.js +9 -0
- package/server/public/filepond-plugin-image-transform.min.js +9 -0
- package/server/public/filepond.min.css +8 -0
- package/server/public/filepond.min.js +9 -0
- package/server/public/fscreator.js +160 -0
- package/server/public/fseditor.js +189 -0
- package/server/public/github.png +0 -0
- package/server/public/opener.js +3 -1
- package/server/public/pinokio-black.png +0 -0
- package/server/public/pinokio-black2.png +0 -0
- package/server/public/style.css +131 -9
- package/server/socket.js +123 -37
- package/server/views/app.ejs +184 -11
- package/server/views/editor.ejs +12 -2
- package/server/views/explore.ejs +4 -3
- package/server/views/help.ejs +4 -2
- package/server/views/index.ejs +218 -80
- package/server/views/install.ejs +1 -1
- package/server/views/local_editor.ejs +282 -0
- package/server/views/minterm.ejs +692 -0
- package/server/views/partials/menu.ejs +7 -1
- package/server/views/prototypes.ejs +463 -0
- package/server/views/proxy.ejs +10 -4
- package/server/views/settings.ejs +4 -3
- package/server/views/terminal.ejs +99 -15
package/server/views/app.ejs
CHANGED
|
@@ -9,11 +9,20 @@
|
|
|
9
9
|
<link href="/css/brands.min.css" rel="stylesheet">
|
|
10
10
|
<link href="/markdown.css" rel="stylesheet"/>
|
|
11
11
|
<link href="/noty.css" rel="stylesheet"/>
|
|
12
|
+
<link href="/filepond.min.css" rel="stylesheet" />
|
|
13
|
+
<link href="/filepond-plugin-image-preview.min.css" rel="stylesheet" />
|
|
14
|
+
<link href="/filepond-plugin-image-edit.min.css" rel="stylesheet" />
|
|
12
15
|
<link href="/style.css" rel="stylesheet"/>
|
|
13
16
|
<% if (agent === "electron") { %>
|
|
14
17
|
<link href="/electron.css" rel="stylesheet"/>
|
|
15
18
|
<% } %>
|
|
16
19
|
<style>
|
|
20
|
+
.online {
|
|
21
|
+
width: 10px;
|
|
22
|
+
height: 10px;
|
|
23
|
+
background: yellowgreen;
|
|
24
|
+
border-radius: 10px;
|
|
25
|
+
}
|
|
17
26
|
#menu {
|
|
18
27
|
display: flex;
|
|
19
28
|
}
|
|
@@ -29,7 +38,9 @@
|
|
|
29
38
|
*/
|
|
30
39
|
}
|
|
31
40
|
#menu.margin {
|
|
41
|
+
/*
|
|
32
42
|
padding: 5px;
|
|
43
|
+
*/
|
|
33
44
|
}
|
|
34
45
|
#menu.margin i {
|
|
35
46
|
display: none;
|
|
@@ -133,7 +144,9 @@ body.dark .header-item .btn2 {
|
|
|
133
144
|
*/
|
|
134
145
|
height: 80px;
|
|
135
146
|
width: 80px;
|
|
147
|
+
/*
|
|
136
148
|
border-radius: 10px;
|
|
149
|
+
*/
|
|
137
150
|
object-fit: contain;
|
|
138
151
|
display: inline-block;
|
|
139
152
|
/*
|
|
@@ -173,6 +186,11 @@ body.dark #new-window {
|
|
|
173
186
|
color: white;
|
|
174
187
|
*/
|
|
175
188
|
}
|
|
189
|
+
/*
|
|
190
|
+
.dark .app-info {
|
|
191
|
+
background: rgba(255,255,255,0.04);
|
|
192
|
+
}
|
|
193
|
+
*/
|
|
176
194
|
.app-info {
|
|
177
195
|
/*
|
|
178
196
|
display: flex;
|
|
@@ -181,10 +199,45 @@ body.dark #new-window {
|
|
|
181
199
|
text-align: center;;
|
|
182
200
|
font-weight: bold;
|
|
183
201
|
align-items: center;
|
|
184
|
-
padding: 20px 0px;
|
|
202
|
+
padding: 20px 0px 0px;
|
|
203
|
+
/*
|
|
204
|
+
background: rgba(0,0,0,0.04);
|
|
205
|
+
*/
|
|
206
|
+
}
|
|
207
|
+
.folderbuttons {
|
|
208
|
+
display: grid;
|
|
209
|
+
grid-template-columns: repeat(4, 1fr);
|
|
210
|
+
gap: 0px;
|
|
211
|
+
}
|
|
212
|
+
.app-info-edit {
|
|
213
|
+
border-bottom: 1px solid rgba(255,255,255,0.1);
|
|
185
214
|
}
|
|
186
|
-
|
|
187
|
-
|
|
215
|
+
/*
|
|
216
|
+
.dark .app-info-edit {
|
|
217
|
+
border-top: 1px solid rgba(255,255,255,0.2);
|
|
218
|
+
border-bottom: 1px solid rgba(255,255,255,0.2);
|
|
219
|
+
}
|
|
220
|
+
*/
|
|
221
|
+
.dark .app-info-edit:hover {
|
|
222
|
+
background: rgba(0,0,0,0.2);
|
|
223
|
+
}
|
|
224
|
+
.app-info-edit:hover{
|
|
225
|
+
background: rgba(0,0,0,0.05);
|
|
226
|
+
}
|
|
227
|
+
.app-info-edit i{
|
|
228
|
+
display: block;
|
|
229
|
+
}
|
|
230
|
+
.app-info-edit, .app-info-copy {
|
|
231
|
+
font-weight: normal;
|
|
232
|
+
|
|
233
|
+
/*
|
|
234
|
+
border-radius: 20px;
|
|
235
|
+
*/
|
|
236
|
+
font-size: 12px;
|
|
237
|
+
padding: 15px 5px;
|
|
238
|
+
/*
|
|
239
|
+
margin: 10px 20px 0;
|
|
240
|
+
*/
|
|
188
241
|
}
|
|
189
242
|
.app-info > * {
|
|
190
243
|
padding: 5px;
|
|
@@ -515,6 +568,23 @@ body.dark .loader-container {
|
|
|
515
568
|
margin-right: 5px;
|
|
516
569
|
font-size: 16px !important;
|
|
517
570
|
}
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
.custom-label {
|
|
574
|
+
position: absolute;
|
|
575
|
+
top: 0;
|
|
576
|
+
left: 0;
|
|
577
|
+
right: 0;
|
|
578
|
+
bottom: 0;
|
|
579
|
+
display: flex;
|
|
580
|
+
align-items: center;
|
|
581
|
+
justify-content: center;
|
|
582
|
+
pointer-events: none; /* Let clicks fall through to FilePond */
|
|
583
|
+
font-size: 14px;
|
|
584
|
+
color: rgba(0, 0, 0, 0.5);
|
|
585
|
+
z-index: 5;
|
|
586
|
+
}
|
|
587
|
+
|
|
518
588
|
@media only screen and (max-width: 480px) {
|
|
519
589
|
nav .btn2 {
|
|
520
590
|
width: auto !important;
|
|
@@ -574,37 +644,61 @@ body.dark .loader-container {
|
|
|
574
644
|
<script src="/Socket.js"></script>
|
|
575
645
|
<script src="/noty.js"></script>
|
|
576
646
|
<script src="/notyq.js"></script>
|
|
647
|
+
<script src="/filepond-plugin-file-validate-type.min.js"></script>
|
|
648
|
+
<script src="/filepond-plugin-image-exif-orientation.min.js"></script>
|
|
649
|
+
<script src="/filepond-plugin-image-preview.min.js"></script>
|
|
650
|
+
<script src="/filepond-plugin-image-edit.min.js"></script>
|
|
651
|
+
<script src="/filepond-plugin-image-crop.min.js"></script>
|
|
652
|
+
<script src="/filepond-plugin-image-resize.min.js"></script>
|
|
653
|
+
<script src="/filepond-plugin-image-transform.min.js"></script>
|
|
654
|
+
<script src="/filepond.min.js"></script>
|
|
655
|
+
<script src="/fseditor.js"></script>
|
|
577
656
|
</head>
|
|
578
657
|
<body class='<%=theme%>' data-platform="<%=platform%>">
|
|
579
658
|
<aside class='active'>
|
|
580
659
|
<div class='header-top header-item'>
|
|
581
660
|
<div class='app-info'>
|
|
582
661
|
<% if (config.icon) { %>
|
|
583
|
-
<img src="<%=
|
|
662
|
+
<img src="<%=config.icon%>"/>
|
|
584
663
|
<% } else { %>
|
|
585
664
|
<i class="fa-regular fa-circle-dot"></i>
|
|
586
665
|
<% } %>
|
|
587
666
|
<div><%=config.title%></div>
|
|
667
|
+
<div class="folderpath">/api/<%=name%></div>
|
|
668
|
+
<div class='folderbuttons'>
|
|
669
|
+
<div class='app-info-edit' id='edit'><i class="fa-solid fa-pen-to-square"></i> Edit</div>
|
|
670
|
+
<div class='app-info-edit' id='move'><i class="fa-solid fa-copy"></i> Move</div>
|
|
671
|
+
<div class='app-info-edit' id='copy'><i class="fa-solid fa-copy"></i> Copy</div>
|
|
672
|
+
<div class='app-info-edit' id='delete' data-name="<%=name%>"><i class="fa-solid fa-trash-can"></i> Delete</div>
|
|
673
|
+
</div>
|
|
588
674
|
</div>
|
|
589
675
|
</div>
|
|
590
676
|
<div class='m n system' data-type="n">
|
|
591
677
|
<!--<a data-index="0" target="<%=src%>" href="<%=src%>" class='btn header-item frame-link'>-->
|
|
678
|
+
<!--
|
|
679
|
+
<div id='copy' data-name="<%=name%>" class='btn header-item frame-link'>
|
|
680
|
+
<div class='tab'><i class="fa-solid fa-copy"></i> Copy</div>
|
|
681
|
+
</div>
|
|
592
682
|
<div id='delete' data-name="<%=name%>" class='btn header-item frame-link'>
|
|
593
683
|
<div class='tab'><i class="fa-solid fa-trash-can"></i> Delete</div>
|
|
594
684
|
</div>
|
|
685
|
+
-->
|
|
595
686
|
<a target="<%=src%>" href="<%=src%>" class='btn header-item frame-link' data-index="0">
|
|
596
687
|
<div class='tab'><i class="fa-regular fa-folder-open"></i> Files <div class='disk-usage'></div></div>
|
|
597
688
|
</a>
|
|
689
|
+
<a target="_blank" href="/terminal/<%=name%>/<%=Date.now()%>" class='btn header-item frame-link' data-index="1">
|
|
690
|
+
<div class='tab'><i class="fa-solid fa-terminal"></i> Terminal</div>
|
|
691
|
+
</a>
|
|
598
692
|
<a target="_blank" href="<%=profile%>" class='btn header-item frame-link'>
|
|
599
693
|
<div class='tab'><i class="fa-regular fa-circle-user"></i> Publisher</div>
|
|
600
694
|
</a>
|
|
601
695
|
<a target="_blank" href="<%=feed%>" class='btn header-item frame-link'>
|
|
602
696
|
<div class='tab'><i class="fa-solid fa-rss"></i> Newsfeed</div>
|
|
603
697
|
</a>
|
|
604
|
-
<a target="/share/<%=name%>" href="/share/<%=name%>", class="btn header-item frame-link" data-index="
|
|
698
|
+
<a target="/share/<%=name%>" href="/share/<%=name%>", class="btn header-item frame-link" data-index="2" data-mode="refresh">
|
|
605
699
|
<div class='tab'><i class="fa-solid fa-wifi"></i> Share</div>
|
|
606
700
|
</a>
|
|
607
|
-
<a target="/env/api/<%=name%>" href="/env/api/<%=name%>", class="btn header-item frame-link" data-index="
|
|
701
|
+
<a target="/env/api/<%=name%>" href="/env/api/<%=name%>", class="btn header-item frame-link" data-index="3" data-mode="refresh">
|
|
608
702
|
<div class='tab'><i class="fa-solid fa-gear"></i> Configure</div>
|
|
609
703
|
</a>
|
|
610
704
|
</div>
|
|
@@ -659,7 +753,7 @@ body.dark .loader-container {
|
|
|
659
753
|
<div class='bar'>
|
|
660
754
|
<button class='btn2' id='menu-mobile'><i class="fa-solid fa-bars"></i></button>
|
|
661
755
|
<button class='btn2' id='menu'>
|
|
662
|
-
<img src="<%=
|
|
756
|
+
<img src="<%=config.icon%>"/>
|
|
663
757
|
<i class="fa-solid fa-arrow-right-to-bracket fa-rotate-180"></i>
|
|
664
758
|
</button>
|
|
665
759
|
<% if (agent === "electron") { %>
|
|
@@ -1215,12 +1309,90 @@ body.dark .loader-container {
|
|
|
1215
1309
|
document.querySelector("#menu").classList.toggle("margin")
|
|
1216
1310
|
})
|
|
1217
1311
|
}
|
|
1218
|
-
document.querySelector("
|
|
1312
|
+
document.querySelector("#move").addEventListener("click", async (e) => {
|
|
1219
1313
|
e.preventDefault()
|
|
1220
1314
|
e.stopPropagation()
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1315
|
+
await FSEditor({
|
|
1316
|
+
title: `<%=config.title%>`,
|
|
1317
|
+
description: `<%=config.description%>`,
|
|
1318
|
+
old_path: `<%=name%>`,
|
|
1319
|
+
icon: `<%=config.icon%>`,
|
|
1320
|
+
iconpath: `<%=config.iconpath%>`,
|
|
1321
|
+
move: true,
|
|
1322
|
+
edit: true,
|
|
1323
|
+
redirect: (new_path) => {
|
|
1324
|
+
return location.href.replace(/(.+pinokio\/[^/]+\/)([^/]+)(\/.*$)/, `$1${new_path}$3`)
|
|
1325
|
+
}
|
|
1326
|
+
})
|
|
1327
|
+
})
|
|
1328
|
+
document.querySelector("#edit").addEventListener("click", async (e) => {
|
|
1329
|
+
e.preventDefault()
|
|
1330
|
+
e.stopPropagation()
|
|
1331
|
+
await FSEditor({
|
|
1332
|
+
title: `<%=config.title%>`,
|
|
1333
|
+
description: `<%=config.description%>`,
|
|
1334
|
+
old_path: `<%=name%>`,
|
|
1335
|
+
icon: `<%=config.icon%>`,
|
|
1336
|
+
iconpath: `<%=config.iconpath%>`,
|
|
1337
|
+
edit: true,
|
|
1338
|
+
redirect: (new_path) => {
|
|
1339
|
+
return location.href.replace(/(.+pinokio\/[^/]+\/)([^/]+)(\/.*$)/, `$1${new_path}$3`)
|
|
1340
|
+
}
|
|
1341
|
+
})
|
|
1342
|
+
})
|
|
1343
|
+
document.querySelector("#copy").addEventListener("click", async (e) => {
|
|
1344
|
+
e.preventDefault()
|
|
1345
|
+
e.stopPropagation()
|
|
1346
|
+
await FSEditor({
|
|
1347
|
+
title: `<%=config.title%>`,
|
|
1348
|
+
description: `<%=config.description%>`,
|
|
1349
|
+
old_path: `<%=name%>`,
|
|
1350
|
+
icon: `<%=config.icon%>`,
|
|
1351
|
+
iconpath: `<%=config.iconpath%>`,
|
|
1352
|
+
copy: true,
|
|
1353
|
+
edit: true,
|
|
1354
|
+
redirect: (new_path) => {
|
|
1355
|
+
return location.href.replace(/(.+pinokio\/[^/]+\/)([^/]+)(\/.*$)/, `$1${new_path}$3`)
|
|
1356
|
+
}
|
|
1357
|
+
})
|
|
1358
|
+
/*
|
|
1359
|
+
e.preventDefault()
|
|
1360
|
+
e.stopPropagation()
|
|
1361
|
+
let folder = prompt("Enter a folder name to copy to")
|
|
1362
|
+
if (folder.includes(' ')) {
|
|
1363
|
+
alert("Please use a folder name without a space")
|
|
1364
|
+
return
|
|
1365
|
+
}
|
|
1366
|
+
Swal.fire({
|
|
1367
|
+
html: `<i class="fa-solid fa-circle-notch fa-spin"></i> Copying from <%=name%> to ${folder}`,
|
|
1368
|
+
customClass: {
|
|
1369
|
+
container: "loader-container",
|
|
1370
|
+
popup: "loader-popup",
|
|
1371
|
+
htmlContainer: "loader-dialog",
|
|
1372
|
+
footer: "hidden",
|
|
1373
|
+
actions: "hidden"
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
let res = await fetch("/copy", {
|
|
1377
|
+
method: "post",
|
|
1378
|
+
headers: {
|
|
1379
|
+
"Content-Type": "application/json"
|
|
1380
|
+
},
|
|
1381
|
+
body: JSON.stringify({
|
|
1382
|
+
src: "<%=name%>",
|
|
1383
|
+
dest: folder
|
|
1384
|
+
})
|
|
1385
|
+
}).then((res) => {
|
|
1386
|
+
return res.json()
|
|
1387
|
+
})
|
|
1388
|
+
Swal.close()
|
|
1389
|
+
if (res.error) {
|
|
1390
|
+
alert(res.error)
|
|
1391
|
+
} else {
|
|
1392
|
+
console.log(res)
|
|
1393
|
+
location.href = res.success
|
|
1394
|
+
}
|
|
1395
|
+
*/
|
|
1224
1396
|
})
|
|
1225
1397
|
document.querySelector("#delete").addEventListener("click", async (e) => {
|
|
1226
1398
|
e.preventDefault()
|
|
@@ -1516,6 +1688,7 @@ body.dark .loader-container {
|
|
|
1516
1688
|
console.log("asideHidden", asideHidden)
|
|
1517
1689
|
if (!asideHidden) {
|
|
1518
1690
|
// refresh only if aside
|
|
1691
|
+
console.log("type", event.data.type)
|
|
1519
1692
|
if (event.data.type === 'disconnect') {
|
|
1520
1693
|
console.log("Refresh 1")
|
|
1521
1694
|
refresh()
|
package/server/views/editor.ejs
CHANGED
|
@@ -113,6 +113,7 @@ body.frozen {
|
|
|
113
113
|
}
|
|
114
114
|
</style>
|
|
115
115
|
<script>
|
|
116
|
+
let shell_id
|
|
116
117
|
document.addEventListener("DOMContentLoaded", async () => {
|
|
117
118
|
<% if (error) { %>
|
|
118
119
|
document.querySelector(".requirements .content").innerHTML = '<div class="loading"><i class="fa-solid fa-circle-exclamation"></i> <%=error%></div>'
|
|
@@ -331,8 +332,17 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
331
332
|
|
|
332
333
|
} else if (packet.type === 'connect') {
|
|
333
334
|
// document.querySelector(".terminal-container").classList.remove("hidden")
|
|
334
|
-
|
|
335
|
-
|
|
335
|
+
if (packet.data.id) {
|
|
336
|
+
shell_id = packet.data.id
|
|
337
|
+
}
|
|
338
|
+
if (packet.data) {
|
|
339
|
+
if (packet.data.shell) {
|
|
340
|
+
shell_id = packet.data.shell
|
|
341
|
+
}
|
|
342
|
+
if (packet.data.state) {
|
|
343
|
+
this.write(packet.data.state)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
336
346
|
/*
|
|
337
347
|
for(let i=0; i<message.length; i++) {
|
|
338
348
|
await new Promise((r, reject) => {
|
package/server/views/explore.ejs
CHANGED
|
@@ -120,8 +120,10 @@ 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>
|
|
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 href="/new" class='btn2'><div><i class='fa-solid fa-folder-plus'></i></div><div>Create</div></a>
|
|
126
|
+
<a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|
|
125
127
|
<% paths.forEach((path) => { %>
|
|
126
128
|
<% if (path.action) { %>
|
|
127
129
|
<a class='path nav-button' id="<%=path.id%>" onclick="<%=path.action%>"><%-path.name%></a>
|
|
@@ -131,7 +133,6 @@ body main iframe {
|
|
|
131
133
|
<% }) %>
|
|
132
134
|
<div class='flexible'></div>
|
|
133
135
|
<div class='nav-btns'>
|
|
134
|
-
<a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|
|
135
136
|
<a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
136
137
|
<a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
|
|
137
138
|
<button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
|
package/server/views/help.ejs
CHANGED
|
@@ -255,8 +255,10 @@ 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 href="/new" class='btn2'><div><i class='fa-solid fa-folder-plus'></i></div><div>Create</div></a>
|
|
261
|
+
<a class='btn2' id='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
264
|
<a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|