pinokiod 3.182.0 → 3.184.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.
- package/package.json +1 -1
- package/server/views/agents.ejs +1 -0
- package/server/views/app.ejs +66 -112
- package/server/views/connect/x.ejs +1 -0
- package/server/views/connect.ejs +1 -0
- package/server/views/container.ejs +1 -0
- package/server/views/download.ejs +1 -0
- package/server/views/explore.ejs +1 -0
- package/server/views/form.ejs +1 -0
- package/server/views/frame.ejs +1 -0
- package/server/views/github.ejs +1 -0
- package/server/views/help.ejs +1 -0
- package/server/views/index.ejs +1 -0
- package/server/views/init/index.ejs +1 -0
- package/server/views/mini.ejs +1 -0
- package/server/views/net.ejs +1 -0
- package/server/views/network.ejs +1 -0
- package/server/views/prototype/index.ejs +1 -0
- package/server/views/review.ejs +1 -0
- package/server/views/screenshots.ejs +1 -0
- package/server/views/settings.ejs +1 -0
- package/server/views/setup.ejs +1 -0
- package/server/views/setup_home.ejs +1 -0
- package/server/views/shell.ejs +105 -3
- package/server/views/terminal.ejs +105 -3
- package/server/views/tools.ejs +1 -0
package/package.json
CHANGED
package/server/views/agents.ejs
CHANGED
|
@@ -410,6 +410,7 @@ body.dark .plugin-option:hover {
|
|
|
410
410
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
411
411
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
412
412
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
413
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
413
414
|
<div class='flexible'></div>
|
|
414
415
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
415
416
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/app.ejs
CHANGED
|
@@ -891,14 +891,6 @@ body.dark .tab-link-popover {
|
|
|
891
891
|
body.dark .tab-link-popover .tab-link-popover-header {
|
|
892
892
|
color: rgba(226, 232, 240, 0.7);
|
|
893
893
|
}
|
|
894
|
-
.tab-link-popover .tab-link-popover-separator {
|
|
895
|
-
height: 1px;
|
|
896
|
-
margin: 4px 14px;
|
|
897
|
-
background: rgba(15, 23, 42, 0.08);
|
|
898
|
-
}
|
|
899
|
-
body.dark .tab-link-popover .tab-link-popover-separator {
|
|
900
|
-
background: rgba(148, 163, 184, 0.18);
|
|
901
|
-
}
|
|
902
894
|
.tab-link-popover .tab-link-popover-item {
|
|
903
895
|
width: 100%;
|
|
904
896
|
border: none;
|
|
@@ -932,10 +924,6 @@ body.dark .tab-link-popover .tab-link-popover-item:focus-visible {
|
|
|
932
924
|
text-transform: uppercase;
|
|
933
925
|
color: rgba(15, 23, 42, 0.55);
|
|
934
926
|
}
|
|
935
|
-
.tab-link-popover .tab-link-popover-item .label i {
|
|
936
|
-
margin-right: 6px;
|
|
937
|
-
font-size: 11px;
|
|
938
|
-
}
|
|
939
927
|
body.dark .tab-link-popover .tab-link-popover-item .label {
|
|
940
928
|
color: rgba(226, 232, 240, 0.65);
|
|
941
929
|
}
|
|
@@ -3098,6 +3086,7 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
|
|
|
3098
3086
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
3099
3087
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
3100
3088
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
3089
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
3101
3090
|
<div class='sep'></div>
|
|
3102
3091
|
<div class='mode-selector'>
|
|
3103
3092
|
<a class="btn2 <%=type === 'review' ? 'selected' : ''%>" href="<%=review_tab%>"><div><i class="fa-regular fa-message"></i></div><div class='caption'>Forum</div></a>
|
|
@@ -4400,27 +4389,27 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
|
|
|
4400
4389
|
positionTabLinkPopover(pop, link)
|
|
4401
4390
|
} catch (_) {}
|
|
4402
4391
|
|
|
4403
|
-
let entries
|
|
4392
|
+
let entries
|
|
4404
4393
|
try {
|
|
4405
|
-
|
|
4406
|
-
if (Array.isArray(result)) {
|
|
4407
|
-
entries = result.slice()
|
|
4408
|
-
}
|
|
4394
|
+
entries = await buildTabLinkEntries(link)
|
|
4409
4395
|
} catch (_) {
|
|
4410
|
-
|
|
4396
|
+
tabLinkPendingLink = null
|
|
4397
|
+
return
|
|
4411
4398
|
}
|
|
4412
4399
|
|
|
4413
4400
|
if (tabLinkPendingLink !== link) {
|
|
4414
4401
|
return
|
|
4415
4402
|
}
|
|
4416
4403
|
|
|
4417
|
-
|
|
4418
|
-
|
|
4404
|
+
if (!entries || entries.length === 0) {
|
|
4405
|
+
hideTabLinkPopover({ immediate: true })
|
|
4406
|
+
return
|
|
4407
|
+
}
|
|
4419
4408
|
|
|
4420
4409
|
if (sameOrigin) {
|
|
4421
4410
|
const slug = extractProjectSlug(link).toLowerCase()
|
|
4422
4411
|
if (slug) {
|
|
4423
|
-
|
|
4412
|
+
entries = entries.filter((entry) => {
|
|
4424
4413
|
if (!entry || !entry.url) {
|
|
4425
4414
|
return false
|
|
4426
4415
|
}
|
|
@@ -4455,21 +4444,17 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
|
|
|
4455
4444
|
return false
|
|
4456
4445
|
})
|
|
4457
4446
|
} else {
|
|
4458
|
-
|
|
4447
|
+
entries = entries.filter((entry) => entry.url === canonicalBase)
|
|
4459
4448
|
}
|
|
4460
4449
|
|
|
4461
|
-
const hasAlternate =
|
|
4450
|
+
const hasAlternate = entries.some((entry) => entry.url !== canonicalBase)
|
|
4462
4451
|
if (!hasAlternate) {
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
} else {
|
|
4466
|
-
showOpenSection = openEntries.length > 0
|
|
4452
|
+
hideTabLinkPopover({ immediate: true })
|
|
4453
|
+
return
|
|
4467
4454
|
}
|
|
4468
|
-
} else {
|
|
4469
|
-
showOpenSection = openEntries.length > 0
|
|
4470
4455
|
}
|
|
4471
4456
|
|
|
4472
|
-
if (!
|
|
4457
|
+
if (!entries || entries.length === 0) {
|
|
4473
4458
|
hideTabLinkPopover({ immediate: true })
|
|
4474
4459
|
return
|
|
4475
4460
|
}
|
|
@@ -4477,93 +4462,62 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
|
|
|
4477
4462
|
const popover = ensureTabLinkPopoverEl()
|
|
4478
4463
|
popover.innerHTML = ""
|
|
4479
4464
|
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
item.append(labelSpan, valueSpan)
|
|
4515
|
-
}
|
|
4516
|
-
popover.appendChild(item)
|
|
4517
|
-
})
|
|
4518
|
-
|
|
4519
|
-
if (tabLinkRouterHttpsActive === false && !hasHttpsEntry) {
|
|
4520
|
-
const footerButton = document.createElement("button")
|
|
4521
|
-
footerButton.type = "button"
|
|
4522
|
-
footerButton.className = "tab-link-popover-item tab-link-popover-footer"
|
|
4523
|
-
footerButton.setAttribute("data-url", "/network")
|
|
4524
|
-
footerButton.setAttribute("data-target", "_self")
|
|
4525
|
-
footerButton.setAttribute("aria-label", "Open network settings to configure local HTTPS")
|
|
4526
|
-
|
|
4527
|
-
const footerLabel = document.createElement("span")
|
|
4528
|
-
footerLabel.className = "label"
|
|
4529
|
-
footerLabel.textContent = "Custom domain not active"
|
|
4530
|
-
|
|
4531
|
-
const footerValue = document.createElement("span")
|
|
4532
|
-
footerValue.className = "value"
|
|
4533
|
-
footerValue.textContent = "Click to activate"
|
|
4534
|
-
|
|
4535
|
-
footerButton.append(footerLabel, footerValue)
|
|
4536
|
-
popover.appendChild(footerButton)
|
|
4465
|
+
const header = document.createElement("div")
|
|
4466
|
+
header.className = "tab-link-popover-header"
|
|
4467
|
+
header.innerHTML = `<i class="fa-solid fa-arrow-up-right-from-square"></i><span>Open in browser</span>`
|
|
4468
|
+
popover.appendChild(header)
|
|
4469
|
+
|
|
4470
|
+
const hasHttpsEntry = entries.some((entry) => entry && entry.type === "https")
|
|
4471
|
+
|
|
4472
|
+
entries.forEach((entry) => {
|
|
4473
|
+
const item = document.createElement("button")
|
|
4474
|
+
item.type = "button"
|
|
4475
|
+
item.setAttribute("data-url", entry.url)
|
|
4476
|
+
const labelSpan = document.createElement("span")
|
|
4477
|
+
labelSpan.className = "label"
|
|
4478
|
+
labelSpan.textContent = entry.label
|
|
4479
|
+
const valueSpan = document.createElement("span")
|
|
4480
|
+
valueSpan.className = "value"
|
|
4481
|
+
valueSpan.textContent = entry.display
|
|
4482
|
+
|
|
4483
|
+
if (entry.type === 'http' && entry.qr === true) {
|
|
4484
|
+
item.className = "tab-link-popover-item qr-inline"
|
|
4485
|
+
const textCol = document.createElement('div')
|
|
4486
|
+
textCol.className = 'textcol'
|
|
4487
|
+
textCol.append(labelSpan, valueSpan)
|
|
4488
|
+
const qrImg = document.createElement('img')
|
|
4489
|
+
qrImg.className = 'qr'
|
|
4490
|
+
qrImg.alt = 'QR'
|
|
4491
|
+
qrImg.decoding = 'async'
|
|
4492
|
+
qrImg.loading = 'lazy'
|
|
4493
|
+
qrImg.src = `/qr?data=${encodeURIComponent(entry.url)}&s=4&m=0`
|
|
4494
|
+
item.append(textCol, qrImg)
|
|
4495
|
+
} else {
|
|
4496
|
+
item.className = "tab-link-popover-item"
|
|
4497
|
+
// Keep label and value as direct children so column layout applies
|
|
4498
|
+
item.append(labelSpan, valueSpan)
|
|
4537
4499
|
}
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
if (showOpenSection && canonicalBase) {
|
|
4541
|
-
const separator = document.createElement("div")
|
|
4542
|
-
separator.className = "tab-link-popover-separator"
|
|
4543
|
-
popover.appendChild(separator)
|
|
4544
|
-
}
|
|
4545
|
-
|
|
4546
|
-
if (canonicalBase) {
|
|
4547
|
-
const debugHeader = document.createElement("div")
|
|
4548
|
-
debugHeader.className = "tab-link-popover-header"
|
|
4549
|
-
debugHeader.innerHTML = `<i class="fa-solid fa-cube"></i><span>Debug</span>`
|
|
4550
|
-
popover.appendChild(debugHeader)
|
|
4500
|
+
popover.appendChild(item)
|
|
4501
|
+
})
|
|
4551
4502
|
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4503
|
+
if (tabLinkRouterHttpsActive === false && !hasHttpsEntry) {
|
|
4504
|
+
const footerButton = document.createElement("button")
|
|
4505
|
+
footerButton.type = "button"
|
|
4506
|
+
footerButton.className = "tab-link-popover-item tab-link-popover-footer"
|
|
4507
|
+
footerButton.setAttribute("data-url", "/network")
|
|
4508
|
+
footerButton.setAttribute("data-target", "_self")
|
|
4509
|
+
footerButton.setAttribute("aria-label", "Open network settings to configure local HTTPS")
|
|
4556
4510
|
|
|
4557
|
-
const
|
|
4558
|
-
|
|
4559
|
-
|
|
4511
|
+
const footerLabel = document.createElement("span")
|
|
4512
|
+
footerLabel.className = "label"
|
|
4513
|
+
footerLabel.textContent = "Custom domain not active"
|
|
4560
4514
|
|
|
4561
|
-
const
|
|
4562
|
-
|
|
4563
|
-
|
|
4515
|
+
const footerValue = document.createElement("span")
|
|
4516
|
+
footerValue.className = "value"
|
|
4517
|
+
footerValue.textContent = "Click to activate"
|
|
4564
4518
|
|
|
4565
|
-
|
|
4566
|
-
popover.appendChild(
|
|
4519
|
+
footerButton.append(footerLabel, footerValue)
|
|
4520
|
+
popover.appendChild(footerButton)
|
|
4567
4521
|
}
|
|
4568
4522
|
|
|
4569
4523
|
tabLinkActiveLink = link
|
|
@@ -201,6 +201,7 @@ pre {
|
|
|
201
201
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
202
202
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
203
203
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
204
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
204
205
|
<div class='flexible'></div>
|
|
205
206
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
206
207
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/connect.ejs
CHANGED
|
@@ -820,6 +820,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
820
820
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
821
821
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
822
822
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
823
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
823
824
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
824
825
|
<form class='urlbar'>
|
|
825
826
|
<div class='url-input-container'>
|
|
@@ -333,6 +333,7 @@ iframe {
|
|
|
333
333
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
334
334
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
335
335
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
336
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
336
337
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
337
338
|
<form class='urlbar'>
|
|
338
339
|
<div class='url-input-container'>
|
|
@@ -129,6 +129,7 @@ body.frozen {
|
|
|
129
129
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
130
130
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
131
131
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
132
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
132
133
|
<div class='flexible'></div>
|
|
133
134
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
134
135
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/explore.ejs
CHANGED
|
@@ -130,6 +130,7 @@ body main iframe {
|
|
|
130
130
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
131
131
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
132
132
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
133
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
133
134
|
<div class='flexible'></div>
|
|
134
135
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
135
136
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/form.ejs
CHANGED
|
@@ -163,6 +163,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
163
163
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
164
164
|
</button>
|
|
165
165
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
166
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
166
167
|
<div class='flexible'></div>
|
|
167
168
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
168
169
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/frame.ejs
CHANGED
|
@@ -93,6 +93,7 @@ main iframe {
|
|
|
93
93
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
94
94
|
</button>
|
|
95
95
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
96
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
96
97
|
<div class='flexible'></div>
|
|
97
98
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
98
99
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/github.ejs
CHANGED
|
@@ -242,6 +242,7 @@ ol {
|
|
|
242
242
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
243
243
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
244
244
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
245
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
245
246
|
<div class='flexible'></div>
|
|
246
247
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
247
248
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/help.ejs
CHANGED
|
@@ -263,6 +263,7 @@ body.dark .item .tile .badge {
|
|
|
263
263
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
264
264
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
265
265
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
266
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
266
267
|
<div class='flexible'></div>
|
|
267
268
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
268
269
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/index.ejs
CHANGED
|
@@ -425,6 +425,7 @@ body.dark aside .current.selected {
|
|
|
425
425
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
426
426
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
427
427
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
428
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
428
429
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
429
430
|
<form class='urlbar'>
|
|
430
431
|
<div class='url-input-container'>
|
|
@@ -1529,6 +1529,7 @@ body.dark .ace-editor {
|
|
|
1529
1529
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
1530
1530
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
1531
1531
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
1532
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
1532
1533
|
<div class='flexible'></div>
|
|
1533
1534
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
1534
1535
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/mini.ejs
CHANGED
|
@@ -763,6 +763,7 @@ body.dark .appcanvas {
|
|
|
763
763
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
764
764
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
765
765
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
766
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
766
767
|
<div class='flexible filler'></div>
|
|
767
768
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
768
769
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/net.ejs
CHANGED
|
@@ -543,6 +543,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
543
543
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
544
544
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
545
545
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
546
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
546
547
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
547
548
|
<form class='urlbar'>
|
|
548
549
|
<div class='url-input-container'>
|
package/server/views/network.ejs
CHANGED
|
@@ -1056,6 +1056,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
1056
1056
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
1057
1057
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
1058
1058
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
1059
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
1059
1060
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
1060
1061
|
<form class='urlbar'>
|
|
1061
1062
|
<div class='url-input-container'>
|
|
@@ -1011,6 +1011,7 @@ body.dark .appcanvas {
|
|
|
1011
1011
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
1012
1012
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
1013
1013
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
1014
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
1014
1015
|
<div class='flexible'></div>
|
|
1015
1016
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
1016
1017
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/review.ejs
CHANGED
|
@@ -945,6 +945,7 @@ body.dark .top-menu .btn2.selected {
|
|
|
945
945
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
946
946
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
947
947
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
948
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
948
949
|
<button class='btn2' id='hidden-placeholder'><i class="fa-solid fa-bars"></i></button>
|
|
949
950
|
<div class='mode-selector'>
|
|
950
951
|
<a class="btn2 <%=type === 'review' ? 'selected' : ''%>" href="<%=review_tab%>"><div><i class="fa-regular fa-message"></i></div><div class='caption'>Forum</div></a>
|
|
@@ -715,6 +715,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
715
715
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
716
716
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
717
717
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
718
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
718
719
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
719
720
|
<form class='urlbar'>
|
|
720
721
|
<div class='url-input-container'>
|
|
@@ -387,6 +387,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
387
387
|
<% } %>
|
|
388
388
|
<% }) %>
|
|
389
389
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
390
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
390
391
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
391
392
|
<form class='urlbar'>
|
|
392
393
|
<div class='url-input-container'>
|
package/server/views/setup.ejs
CHANGED
|
@@ -140,6 +140,7 @@ body {
|
|
|
140
140
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
141
141
|
</button>
|
|
142
142
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
143
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
143
144
|
<div class='flexible'></div>
|
|
144
145
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
145
146
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
|
@@ -156,6 +156,7 @@ body.dark .card {
|
|
|
156
156
|
<div><i class="fa-solid fa-expand"></i></div>
|
|
157
157
|
</button>
|
|
158
158
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
159
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
159
160
|
<div class='flexible'></div>
|
|
160
161
|
<a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
|
|
161
162
|
<div><i class="fa-solid fa-table-columns"></i></div>
|
package/server/views/shell.ejs
CHANGED
|
@@ -893,6 +893,93 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
893
893
|
}
|
|
894
894
|
}
|
|
895
895
|
}
|
|
896
|
+
async collectFilesFromDataTransfer(dataTransfer) {
|
|
897
|
+
if (!dataTransfer) {
|
|
898
|
+
return []
|
|
899
|
+
}
|
|
900
|
+
const items = dataTransfer.items ? Array.from(dataTransfer.items) : []
|
|
901
|
+
const stringItems = items.filter((item) => item && item.kind === "string" && typeof item.getAsString === "function")
|
|
902
|
+
const collectedStrings = []
|
|
903
|
+
if (stringItems.length > 0) {
|
|
904
|
+
const stringValues = await Promise.all(stringItems.map((item) => new Promise((resolve) => {
|
|
905
|
+
try {
|
|
906
|
+
item.getAsString((value) => resolve({ type: item.type || "text/plain", value }))
|
|
907
|
+
} catch (_) {
|
|
908
|
+
resolve({ type: item.type || "text/plain", value: "" })
|
|
909
|
+
}
|
|
910
|
+
})))
|
|
911
|
+
for (const entry of stringValues) {
|
|
912
|
+
if (entry && typeof entry.value === "string" && entry.value.trim()) {
|
|
913
|
+
collectedStrings.push(entry)
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
} else if (typeof dataTransfer.getData === "function") {
|
|
917
|
+
const uriList = dataTransfer.getData("text/uri-list")
|
|
918
|
+
if (uriList && uriList.trim()) {
|
|
919
|
+
collectedStrings.push({ type: "text/uri-list", value: uriList })
|
|
920
|
+
}
|
|
921
|
+
const plain = dataTransfer.getData("text/plain")
|
|
922
|
+
if (plain && plain.trim()) {
|
|
923
|
+
collectedStrings.push({ type: "text/plain", value: plain })
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
if (!collectedStrings.length) {
|
|
927
|
+
return []
|
|
928
|
+
}
|
|
929
|
+
const origin = window.location.origin
|
|
930
|
+
const urls = new Set()
|
|
931
|
+
for (const { type, value } of collectedStrings) {
|
|
932
|
+
if (!value) {
|
|
933
|
+
continue
|
|
934
|
+
}
|
|
935
|
+
const trimmed = value.trim()
|
|
936
|
+
if (!trimmed) {
|
|
937
|
+
continue
|
|
938
|
+
}
|
|
939
|
+
const candidates = (type === "text/uri-list" ? trimmed.split(/\r?\n/) : [trimmed]).filter((line) => line && !line.startsWith("#"))
|
|
940
|
+
for (const candidate of candidates) {
|
|
941
|
+
let resolved
|
|
942
|
+
try {
|
|
943
|
+
resolved = new URL(candidate, origin)
|
|
944
|
+
} catch (_) {
|
|
945
|
+
continue
|
|
946
|
+
}
|
|
947
|
+
if (resolved.origin !== origin) {
|
|
948
|
+
continue
|
|
949
|
+
}
|
|
950
|
+
urls.add(resolved.href)
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (!urls.size) {
|
|
954
|
+
return []
|
|
955
|
+
}
|
|
956
|
+
const FileCtor = typeof window !== "undefined" ? window.File : null
|
|
957
|
+
if (typeof FileCtor !== "function") {
|
|
958
|
+
return []
|
|
959
|
+
}
|
|
960
|
+
const files = []
|
|
961
|
+
for (const href of urls) {
|
|
962
|
+
try {
|
|
963
|
+
const response = await fetch(href, { credentials: "include" })
|
|
964
|
+
if (!response || !response.ok) {
|
|
965
|
+
continue
|
|
966
|
+
}
|
|
967
|
+
const blob = await response.blob()
|
|
968
|
+
const nameSegment = href.split("/").pop() || "download"
|
|
969
|
+
let filename = nameSegment || "download"
|
|
970
|
+
try {
|
|
971
|
+
filename = decodeURIComponent(filename)
|
|
972
|
+
} catch (_) {}
|
|
973
|
+
if (!filename) {
|
|
974
|
+
filename = "download"
|
|
975
|
+
}
|
|
976
|
+
files.push(new FileCtor([blob], filename, { type: blob.type || "application/octet-stream", lastModified: Date.now() }))
|
|
977
|
+
} catch (error) {
|
|
978
|
+
console.warn("Failed to resolve dropped resource", href, error)
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
return files
|
|
982
|
+
}
|
|
896
983
|
async createTerm (_theme) {
|
|
897
984
|
console.log(xtermTheme)
|
|
898
985
|
if (!this.term) {
|
|
@@ -964,11 +1051,26 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
964
1051
|
prevent(event)
|
|
965
1052
|
dragDepth = 0
|
|
966
1053
|
dropOverlay.classList.remove("active")
|
|
967
|
-
const
|
|
968
|
-
|
|
1054
|
+
const files = Array.from(event.dataTransfer ? event.dataTransfer.files || [] : [])
|
|
1055
|
+
try {
|
|
1056
|
+
const extra = await this.collectFilesFromDataTransfer(event.dataTransfer)
|
|
1057
|
+
if (Array.isArray(extra) && extra.length) {
|
|
1058
|
+
const seen = new Set(files.map((file) => `${file.name}-${file.size}`))
|
|
1059
|
+
for (const file of extra) {
|
|
1060
|
+
const key = `${file.name}-${file.size}`
|
|
1061
|
+
if (!seen.has(key)) {
|
|
1062
|
+
seen.add(key)
|
|
1063
|
+
files.push(file)
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
} catch (error) {
|
|
1068
|
+
console.warn("Failed to collect files from drop payload", error)
|
|
1069
|
+
}
|
|
1070
|
+
if (!files.length) {
|
|
969
1071
|
return
|
|
970
1072
|
}
|
|
971
|
-
await this.uploadFiles(
|
|
1073
|
+
await this.uploadFiles(files, dropOverlay)
|
|
972
1074
|
this.term.focus()
|
|
973
1075
|
})
|
|
974
1076
|
term.attachCustomKeyEventHandler(event => {
|
|
@@ -980,6 +980,93 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
980
980
|
}
|
|
981
981
|
}
|
|
982
982
|
}
|
|
983
|
+
async collectFilesFromDataTransfer(dataTransfer) {
|
|
984
|
+
if (!dataTransfer) {
|
|
985
|
+
return []
|
|
986
|
+
}
|
|
987
|
+
const items = dataTransfer.items ? Array.from(dataTransfer.items) : []
|
|
988
|
+
const stringItems = items.filter((item) => item && item.kind === "string" && typeof item.getAsString === "function")
|
|
989
|
+
const collectedStrings = []
|
|
990
|
+
if (stringItems.length > 0) {
|
|
991
|
+
const stringValues = await Promise.all(stringItems.map((item) => new Promise((resolve) => {
|
|
992
|
+
try {
|
|
993
|
+
item.getAsString((value) => resolve({ type: item.type || "text/plain", value }))
|
|
994
|
+
} catch (_) {
|
|
995
|
+
resolve({ type: item.type || "text/plain", value: "" })
|
|
996
|
+
}
|
|
997
|
+
})))
|
|
998
|
+
for (const entry of stringValues) {
|
|
999
|
+
if (entry && typeof entry.value === "string" && entry.value.trim()) {
|
|
1000
|
+
collectedStrings.push(entry)
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
} else if (typeof dataTransfer.getData === "function") {
|
|
1004
|
+
const uriList = dataTransfer.getData("text/uri-list")
|
|
1005
|
+
if (uriList && uriList.trim()) {
|
|
1006
|
+
collectedStrings.push({ type: "text/uri-list", value: uriList })
|
|
1007
|
+
}
|
|
1008
|
+
const plain = dataTransfer.getData("text/plain")
|
|
1009
|
+
if (plain && plain.trim()) {
|
|
1010
|
+
collectedStrings.push({ type: "text/plain", value: plain })
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
if (!collectedStrings.length) {
|
|
1014
|
+
return []
|
|
1015
|
+
}
|
|
1016
|
+
const origin = window.location.origin
|
|
1017
|
+
const urls = new Set()
|
|
1018
|
+
for (const { type, value } of collectedStrings) {
|
|
1019
|
+
if (!value) {
|
|
1020
|
+
continue
|
|
1021
|
+
}
|
|
1022
|
+
const trimmed = value.trim()
|
|
1023
|
+
if (!trimmed) {
|
|
1024
|
+
continue
|
|
1025
|
+
}
|
|
1026
|
+
const candidates = (type === "text/uri-list" ? trimmed.split(/\r?\n/) : [trimmed]).filter((line) => line && !line.startsWith("#"))
|
|
1027
|
+
for (const candidate of candidates) {
|
|
1028
|
+
let resolved
|
|
1029
|
+
try {
|
|
1030
|
+
resolved = new URL(candidate, origin)
|
|
1031
|
+
} catch (_) {
|
|
1032
|
+
continue
|
|
1033
|
+
}
|
|
1034
|
+
if (resolved.origin !== origin) {
|
|
1035
|
+
continue
|
|
1036
|
+
}
|
|
1037
|
+
urls.add(resolved.href)
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
if (!urls.size) {
|
|
1041
|
+
return []
|
|
1042
|
+
}
|
|
1043
|
+
const FileCtor = typeof window !== "undefined" ? window.File : null
|
|
1044
|
+
if (typeof FileCtor !== "function") {
|
|
1045
|
+
return []
|
|
1046
|
+
}
|
|
1047
|
+
const files = []
|
|
1048
|
+
for (const href of urls) {
|
|
1049
|
+
try {
|
|
1050
|
+
const response = await fetch(href, { credentials: "include" })
|
|
1051
|
+
if (!response || !response.ok) {
|
|
1052
|
+
continue
|
|
1053
|
+
}
|
|
1054
|
+
const blob = await response.blob()
|
|
1055
|
+
const nameSegment = href.split("/").pop() || "download"
|
|
1056
|
+
let filename = nameSegment || "download"
|
|
1057
|
+
try {
|
|
1058
|
+
filename = decodeURIComponent(filename)
|
|
1059
|
+
} catch (_) {}
|
|
1060
|
+
if (!filename) {
|
|
1061
|
+
filename = "download"
|
|
1062
|
+
}
|
|
1063
|
+
files.push(new FileCtor([blob], filename, { type: blob.type || "application/octet-stream", lastModified: Date.now() }))
|
|
1064
|
+
} catch (error) {
|
|
1065
|
+
console.warn("Failed to resolve dropped resource", href, error)
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
return files
|
|
1069
|
+
}
|
|
983
1070
|
async createTerm (_theme) {
|
|
984
1071
|
if (!this.term) {
|
|
985
1072
|
const theme = Object.assign({ }, _theme, {
|
|
@@ -1048,11 +1135,26 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1048
1135
|
prevent(event)
|
|
1049
1136
|
dragDepth = 0
|
|
1050
1137
|
dropOverlay.classList.remove("active")
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1138
|
+
const files = Array.from(event.dataTransfer ? event.dataTransfer.files || [] : [])
|
|
1139
|
+
try {
|
|
1140
|
+
const extra = await this.collectFilesFromDataTransfer(event.dataTransfer)
|
|
1141
|
+
if (Array.isArray(extra) && extra.length) {
|
|
1142
|
+
const seen = new Set(files.map((file) => `${file.name}-${file.size}`))
|
|
1143
|
+
for (const file of extra) {
|
|
1144
|
+
const key = `${file.name}-${file.size}`
|
|
1145
|
+
if (!seen.has(key)) {
|
|
1146
|
+
seen.add(key)
|
|
1147
|
+
files.push(file)
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
} catch (error) {
|
|
1152
|
+
console.warn("Failed to collect files from drop payload", error)
|
|
1153
|
+
}
|
|
1154
|
+
if (!files.length) {
|
|
1053
1155
|
return
|
|
1054
1156
|
}
|
|
1055
|
-
await this.uploadFiles(
|
|
1157
|
+
await this.uploadFiles(files, dropOverlay)
|
|
1056
1158
|
this.term.focus()
|
|
1057
1159
|
})
|
|
1058
1160
|
term.attachCustomKeyEventHandler(event => {
|
package/server/views/tools.ejs
CHANGED
|
@@ -1105,6 +1105,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
1105
1105
|
<button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
|
|
1106
1106
|
<button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
|
|
1107
1107
|
<button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
|
|
1108
|
+
<button class='btn2' id='inspector' data-tippy-content="Switch to inspect mode"><i class="fa-solid fa-eye"></i></button>
|
|
1108
1109
|
<button class='btn2 mobile-link-button' id='mobile-link-button' data-tippy-content="enter url"><i class="fa-solid fa-link"></i></button>
|
|
1109
1110
|
<form class='urlbar'>
|
|
1110
1111
|
<div class='url-input-container'>
|