pinokiod 7.5.21 → 7.5.24
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/index.js +20 -8
- package/kernel/plugin_sources.js +8 -0
- package/package.json +1 -1
- package/server/index.js +113 -13
- package/server/lib/plugin_delete.js +89 -0
- package/server/public/common.js +6 -2
- package/server/public/plugin-detail.js +131 -1
- package/server/public/task-launcher.css +221 -17
- package/server/public/universal-launcher.js +2 -1
- package/server/socket.js +59 -99
- package/server/views/app.ejs +141 -20
- package/server/views/plugin_detail.ejs +52 -20
- package/server/views/plugins.ejs +14 -1
- package/server/views/terminal.ejs +11 -5
- package/test/launch-requirements.test.js +27 -0
- package/test/plugin-delete.test.js +143 -0
- package/test/plugin-detail-ui.test.js +269 -0
- package/test/plugin-detail-view.test.js +160 -0
- package/test/plugin-sources.test.js +19 -0
- package/test/terminal-log-paths.test.js +238 -0
- package/test/universal-launcher.smoke.spec.js +50 -0
package/server/views/app.ejs
CHANGED
|
@@ -727,27 +727,38 @@ body.dark .browserview-network-status .browserview-network-status-secondary:focu
|
|
|
727
727
|
75% { transform: translate(0, 11px); }
|
|
728
728
|
}
|
|
729
729
|
.community-drawer {
|
|
730
|
-
display:
|
|
731
|
-
flex: 0 0
|
|
732
|
-
width:
|
|
733
|
-
min-width:
|
|
730
|
+
display: flex;
|
|
731
|
+
flex: 0 0 0;
|
|
732
|
+
width: 0;
|
|
733
|
+
min-width: 0;
|
|
734
|
+
max-width: 0;
|
|
734
735
|
min-height: 0;
|
|
735
|
-
|
|
736
|
+
box-sizing: border-box;
|
|
737
|
+
border-left: 0 solid rgba(0,0,0,0.08);
|
|
736
738
|
background: #f7f8fa;
|
|
739
|
+
opacity: 0;
|
|
740
|
+
overflow: hidden;
|
|
741
|
+
pointer-events: none;
|
|
742
|
+
transform: translateX(10px);
|
|
737
743
|
}
|
|
738
744
|
body.dark .community-drawer {
|
|
739
745
|
border-left-color: rgba(255,255,255,0.08);
|
|
740
746
|
background: #0f1115;
|
|
741
747
|
}
|
|
742
748
|
.community-resizer {
|
|
743
|
-
display:
|
|
744
|
-
flex: 0 0
|
|
749
|
+
display: flex;
|
|
750
|
+
flex: 0 0 0;
|
|
751
|
+
width: 0;
|
|
752
|
+
min-width: 0;
|
|
745
753
|
align-items: stretch;
|
|
746
754
|
justify-content: center;
|
|
747
755
|
cursor: col-resize;
|
|
748
756
|
touch-action: none;
|
|
749
757
|
outline: none;
|
|
750
758
|
background: transparent;
|
|
759
|
+
opacity: 0;
|
|
760
|
+
overflow: hidden;
|
|
761
|
+
pointer-events: none;
|
|
751
762
|
}
|
|
752
763
|
.community-resizer::before {
|
|
753
764
|
content: '';
|
|
@@ -773,13 +784,27 @@ body.dark .community-resizer:focus-visible::before {
|
|
|
773
784
|
background: var(--pinokio-sidebar-separator-focus, rgba(96, 165, 250, 0.6));
|
|
774
785
|
}
|
|
775
786
|
.appcanvas.community-open .community-resizer {
|
|
776
|
-
|
|
787
|
+
flex: 0 0 7px;
|
|
788
|
+
width: 7px;
|
|
789
|
+
min-width: 7px;
|
|
790
|
+
opacity: 1;
|
|
791
|
+
pointer-events: auto;
|
|
777
792
|
}
|
|
778
793
|
.appcanvas.community-open .community-drawer {
|
|
779
|
-
|
|
794
|
+
flex: 0 0 var(--community-width, 360px);
|
|
795
|
+
width: var(--community-width, 360px);
|
|
796
|
+
max-width: var(--community-width, 360px);
|
|
797
|
+
border-left-width: 1px;
|
|
798
|
+
opacity: 1;
|
|
799
|
+
pointer-events: auto;
|
|
800
|
+
transform: translateX(0);
|
|
780
801
|
}
|
|
781
802
|
.appcanvas.community-expanded .community-resizer {
|
|
782
|
-
|
|
803
|
+
flex-basis: 0;
|
|
804
|
+
width: 0;
|
|
805
|
+
min-width: 0;
|
|
806
|
+
opacity: 0;
|
|
807
|
+
pointer-events: none;
|
|
783
808
|
}
|
|
784
809
|
.appcanvas.community-expanded .community-drawer {
|
|
785
810
|
position: absolute;
|
|
@@ -1362,27 +1387,38 @@ body.dark .mobile-nav-logs.has-new::after {
|
|
|
1362
1387
|
}
|
|
1363
1388
|
}
|
|
1364
1389
|
.ask-ai-drawer {
|
|
1365
|
-
display:
|
|
1366
|
-
flex: 0 0
|
|
1367
|
-
width:
|
|
1368
|
-
min-width:
|
|
1390
|
+
display: flex;
|
|
1391
|
+
flex: 0 0 0;
|
|
1392
|
+
width: 0;
|
|
1393
|
+
min-width: 0;
|
|
1394
|
+
max-width: 0;
|
|
1369
1395
|
min-height: 0;
|
|
1370
|
-
|
|
1396
|
+
box-sizing: border-box;
|
|
1397
|
+
border-left: 0 solid rgba(0,0,0,0.08);
|
|
1371
1398
|
background: #f8fafc;
|
|
1399
|
+
opacity: 0;
|
|
1400
|
+
overflow: hidden;
|
|
1401
|
+
pointer-events: none;
|
|
1402
|
+
transform: translateX(10px);
|
|
1372
1403
|
}
|
|
1373
1404
|
body.dark .ask-ai-drawer {
|
|
1374
1405
|
border-left-color: rgba(255,255,255,0.08);
|
|
1375
1406
|
background: #0f1115;
|
|
1376
1407
|
}
|
|
1377
1408
|
.ask-ai-resizer {
|
|
1378
|
-
display:
|
|
1379
|
-
flex: 0 0
|
|
1409
|
+
display: flex;
|
|
1410
|
+
flex: 0 0 0;
|
|
1411
|
+
width: 0;
|
|
1412
|
+
min-width: 0;
|
|
1380
1413
|
align-items: stretch;
|
|
1381
1414
|
justify-content: center;
|
|
1382
1415
|
cursor: col-resize;
|
|
1383
1416
|
touch-action: none;
|
|
1384
1417
|
outline: none;
|
|
1385
1418
|
background: transparent;
|
|
1419
|
+
opacity: 0;
|
|
1420
|
+
overflow: hidden;
|
|
1421
|
+
pointer-events: none;
|
|
1386
1422
|
}
|
|
1387
1423
|
.ask-ai-resizer::before {
|
|
1388
1424
|
content: '';
|
|
@@ -1408,10 +1444,20 @@ body.dark .ask-ai-resizer:focus-visible::before {
|
|
|
1408
1444
|
background: var(--pinokio-sidebar-separator-focus, rgba(96, 165, 250, 0.6));
|
|
1409
1445
|
}
|
|
1410
1446
|
.appcanvas.panel-open .ask-ai-resizer {
|
|
1411
|
-
|
|
1447
|
+
flex: 0 0 7px;
|
|
1448
|
+
width: 7px;
|
|
1449
|
+
min-width: 7px;
|
|
1450
|
+
opacity: 1;
|
|
1451
|
+
pointer-events: auto;
|
|
1412
1452
|
}
|
|
1413
1453
|
.appcanvas.panel-open .ask-ai-drawer {
|
|
1414
|
-
|
|
1454
|
+
flex: 0 0 var(--ask-ai-width, 560px);
|
|
1455
|
+
width: var(--ask-ai-width, 560px);
|
|
1456
|
+
max-width: var(--ask-ai-width, 560px);
|
|
1457
|
+
border-left-width: 1px;
|
|
1458
|
+
opacity: 1;
|
|
1459
|
+
pointer-events: auto;
|
|
1460
|
+
transform: translateX(0);
|
|
1415
1461
|
}
|
|
1416
1462
|
.ask-ai-drawer-inner {
|
|
1417
1463
|
display: flex;
|
|
@@ -2088,12 +2134,26 @@ body.dark .appcanvas > aside {
|
|
|
2088
2134
|
transition: flex-basis 190ms cubic-bezier(0.25, 1, 0.5, 1), width 190ms cubic-bezier(0.25, 1, 0.5, 1), max-width 190ms cubic-bezier(0.25, 1, 0.5, 1), margin 190ms cubic-bezier(0.25, 1, 0.5, 1), opacity 140ms cubic-bezier(0.25, 1, 0.5, 1), transform 190ms cubic-bezier(0.25, 1, 0.5, 1);
|
|
2089
2135
|
}
|
|
2090
2136
|
|
|
2137
|
+
.appcanvas.right-panel-motion-ready .ask-ai-drawer,
|
|
2138
|
+
.appcanvas.right-panel-motion-ready .ask-ai-resizer,
|
|
2139
|
+
.appcanvas.right-panel-motion-ready .community-drawer,
|
|
2140
|
+
.appcanvas.right-panel-motion-ready .community-resizer {
|
|
2141
|
+
transition: flex-basis 190ms cubic-bezier(0.25, 1, 0.5, 1), width 190ms cubic-bezier(0.25, 1, 0.5, 1), max-width 190ms cubic-bezier(0.25, 1, 0.5, 1), min-width 190ms cubic-bezier(0.25, 1, 0.5, 1), opacity 140ms cubic-bezier(0.25, 1, 0.5, 1), transform 190ms cubic-bezier(0.25, 1, 0.5, 1);
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2091
2144
|
.appcanvas.sidebar-resizing > aside,
|
|
2092
2145
|
.appcanvas.sidebar-resizing > aside .menu-container,
|
|
2093
2146
|
.appcanvas.sidebar-resizing .appcanvas-resizer {
|
|
2094
2147
|
transition: none !important;
|
|
2095
2148
|
}
|
|
2096
2149
|
|
|
2150
|
+
.appcanvas.right-panel-resizing .ask-ai-drawer,
|
|
2151
|
+
.appcanvas.right-panel-resizing .ask-ai-resizer,
|
|
2152
|
+
.appcanvas.right-panel-resizing .community-drawer,
|
|
2153
|
+
.appcanvas.right-panel-resizing .community-resizer {
|
|
2154
|
+
transition: none !important;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2097
2157
|
.appcanvas.sidebar-collapsed > aside {
|
|
2098
2158
|
flex: 0 0 0;
|
|
2099
2159
|
width: 0;
|
|
@@ -2125,7 +2185,11 @@ body.dark .appcanvas > aside {
|
|
|
2125
2185
|
.sidebar-toggle-content,
|
|
2126
2186
|
.appcanvas.sidebar-motion-ready > aside,
|
|
2127
2187
|
.appcanvas.sidebar-motion-ready > aside .menu-container,
|
|
2128
|
-
.appcanvas.sidebar-motion-ready .appcanvas-resizer
|
|
2188
|
+
.appcanvas.sidebar-motion-ready .appcanvas-resizer,
|
|
2189
|
+
.appcanvas.right-panel-motion-ready .ask-ai-drawer,
|
|
2190
|
+
.appcanvas.right-panel-motion-ready .ask-ai-resizer,
|
|
2191
|
+
.appcanvas.right-panel-motion-ready .community-drawer,
|
|
2192
|
+
.appcanvas.right-panel-motion-ready .community-resizer {
|
|
2129
2193
|
transition-duration: 0.01ms !important;
|
|
2130
2194
|
}
|
|
2131
2195
|
}
|
|
@@ -7147,6 +7211,9 @@ header.navheader h1 {
|
|
|
7147
7211
|
}
|
|
7148
7212
|
.appcanvas.community-mode .community-drawer {
|
|
7149
7213
|
display: flex;
|
|
7214
|
+
opacity: 1;
|
|
7215
|
+
pointer-events: auto;
|
|
7216
|
+
transform: translateX(0);
|
|
7150
7217
|
width: 100%;
|
|
7151
7218
|
max-width: none;
|
|
7152
7219
|
border-left: 0;
|
|
@@ -16461,9 +16528,20 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
16461
16528
|
askAiTrigger.setAttribute("aria-hidden", "false")
|
|
16462
16529
|
askAiTrigger.setAttribute("aria-expanded", open ? "true" : "false")
|
|
16463
16530
|
}
|
|
16531
|
+
if (!open && drawer.contains(document.activeElement) && askAiTrigger) {
|
|
16532
|
+
try {
|
|
16533
|
+
askAiTrigger.focus({ preventScroll: true })
|
|
16534
|
+
} catch (_) {
|
|
16535
|
+
askAiTrigger.focus()
|
|
16536
|
+
}
|
|
16537
|
+
}
|
|
16464
16538
|
drawer.setAttribute("aria-hidden", open ? "false" : "true")
|
|
16539
|
+
if ("inert" in drawer) {
|
|
16540
|
+
drawer.inert = !open
|
|
16541
|
+
}
|
|
16465
16542
|
if (resizer) {
|
|
16466
16543
|
resizer.setAttribute("aria-hidden", open ? "false" : "true")
|
|
16544
|
+
resizer.tabIndex = open ? 0 : -1
|
|
16467
16545
|
}
|
|
16468
16546
|
}
|
|
16469
16547
|
|
|
@@ -17174,6 +17252,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
17174
17252
|
let handlePointerUp = null
|
|
17175
17253
|
|
|
17176
17254
|
const finishResizing = () => {
|
|
17255
|
+
if (appcanvas) {
|
|
17256
|
+
appcanvas.classList.remove("right-panel-resizing")
|
|
17257
|
+
}
|
|
17177
17258
|
if (!isResizing) {
|
|
17178
17259
|
return
|
|
17179
17260
|
}
|
|
@@ -17220,6 +17301,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
17220
17301
|
}
|
|
17221
17302
|
event.preventDefault()
|
|
17222
17303
|
isResizing = true
|
|
17304
|
+
if (appcanvas) {
|
|
17305
|
+
appcanvas.classList.add("right-panel-resizing")
|
|
17306
|
+
}
|
|
17223
17307
|
pointerId = event.pointerId
|
|
17224
17308
|
startX = event.clientX
|
|
17225
17309
|
startWidth = drawer.getBoundingClientRect().width
|
|
@@ -17938,6 +18022,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
17938
18022
|
}
|
|
17939
18023
|
appcanvas.classList.toggle("community-mode", communityMode)
|
|
17940
18024
|
if (communityMode) {
|
|
18025
|
+
const ensureOpen = () => {
|
|
18026
|
+
if (communityMode && !open) {
|
|
18027
|
+
setOpen(true, { persist: false })
|
|
18028
|
+
}
|
|
18029
|
+
}
|
|
18030
|
+
if (window.queueMicrotask) {
|
|
18031
|
+
window.queueMicrotask(ensureOpen)
|
|
18032
|
+
} else {
|
|
18033
|
+
setTimeout(ensureOpen, 0)
|
|
18034
|
+
}
|
|
17941
18035
|
setExpanded(false)
|
|
17942
18036
|
}
|
|
17943
18037
|
if (communityModeToggle) {
|
|
@@ -18059,9 +18153,20 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
18059
18153
|
toggle.classList.toggle("selected", open)
|
|
18060
18154
|
toggle.setAttribute("aria-expanded", open ? "true" : "false")
|
|
18061
18155
|
}
|
|
18156
|
+
if (!open && drawer.contains(document.activeElement) && toggle) {
|
|
18157
|
+
try {
|
|
18158
|
+
toggle.focus({ preventScroll: true })
|
|
18159
|
+
} catch (_) {
|
|
18160
|
+
toggle.focus()
|
|
18161
|
+
}
|
|
18162
|
+
}
|
|
18062
18163
|
drawer.setAttribute("aria-hidden", open ? "false" : "true")
|
|
18164
|
+
if ("inert" in drawer) {
|
|
18165
|
+
drawer.inert = !open
|
|
18166
|
+
}
|
|
18063
18167
|
if (resizer) {
|
|
18064
18168
|
resizer.setAttribute("aria-hidden", open ? "false" : "true")
|
|
18169
|
+
resizer.tabIndex = open ? 0 : -1
|
|
18065
18170
|
}
|
|
18066
18171
|
if (persist) {
|
|
18067
18172
|
try {
|
|
@@ -18541,6 +18646,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
18541
18646
|
let handlePointerUp = null
|
|
18542
18647
|
|
|
18543
18648
|
const finishResizing = () => {
|
|
18649
|
+
if (appcanvas) {
|
|
18650
|
+
appcanvas.classList.remove("right-panel-resizing")
|
|
18651
|
+
}
|
|
18544
18652
|
if (!isResizing) {
|
|
18545
18653
|
return
|
|
18546
18654
|
}
|
|
@@ -18593,6 +18701,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
18593
18701
|
}
|
|
18594
18702
|
event.preventDefault()
|
|
18595
18703
|
isResizing = true
|
|
18704
|
+
if (appcanvas) {
|
|
18705
|
+
appcanvas.classList.add("right-panel-resizing")
|
|
18706
|
+
}
|
|
18596
18707
|
pointerId = event.pointerId
|
|
18597
18708
|
startX = event.clientX
|
|
18598
18709
|
startWidth = drawer.getBoundingClientRect().width
|
|
@@ -18604,6 +18715,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
18604
18715
|
}
|
|
18605
18716
|
})()
|
|
18606
18717
|
|
|
18718
|
+
;(function() {
|
|
18719
|
+
const appcanvas = document.querySelector(".appcanvas")
|
|
18720
|
+
if (!appcanvas) {
|
|
18721
|
+
return
|
|
18722
|
+
}
|
|
18723
|
+
requestAnimationFrame(() => {
|
|
18724
|
+
appcanvas.classList.add("right-panel-motion-ready")
|
|
18725
|
+
})
|
|
18726
|
+
})()
|
|
18727
|
+
|
|
18607
18728
|
<%- include('partials/launch_requirements_status_client') %>
|
|
18608
18729
|
|
|
18609
18730
|
;(function() {
|
|
@@ -18,15 +18,35 @@
|
|
|
18
18
|
</head>
|
|
19
19
|
<body class="<%= theme %> main-sidebar-page task-launcher-page task-page plugin-page plugin-detail-page" data-agent="<%= agent %>">
|
|
20
20
|
<% const currentPluginCwd = typeof pluginCwd === "string" ? pluginCwd : ""; %>
|
|
21
|
+
<%
|
|
22
|
+
const pluginDetailHref = plugin.pluginPath
|
|
23
|
+
? `/plugin?path=${encodeURIComponent(plugin.pluginPath)}`
|
|
24
|
+
: "/plugin"
|
|
25
|
+
const githubStatusValue = !shareState.manageable
|
|
26
|
+
? "Read only"
|
|
27
|
+
: shareState.remoteWebUrl && !shareState.hasPublished
|
|
28
|
+
? "Remote created"
|
|
29
|
+
: shareState.remoteWebUrl && ((Number(shareState.changeCount || 0) > 0) || (Number(shareState.aheadCount || 0) > 0))
|
|
30
|
+
? "Out of date"
|
|
31
|
+
: shareState.remoteWebUrl
|
|
32
|
+
? "Connected"
|
|
33
|
+
: shareState.gitInitialized
|
|
34
|
+
? "Local only"
|
|
35
|
+
: "Setup needed"
|
|
36
|
+
const canDeletePlugin = Boolean(plugin.pluginPath && shareState && shareState.ownership === "local" && shareState.dir)
|
|
37
|
+
const showHeaderWebsite = Boolean(!pluginUi.showSidebar && plugin.link)
|
|
38
|
+
%>
|
|
21
39
|
<%- include('partials/app_navheader', { agent }) %>
|
|
22
40
|
<main>
|
|
23
41
|
<div class="task-container">
|
|
24
42
|
<section class="task-shell">
|
|
25
43
|
<header class="task-shell-header">
|
|
26
44
|
<div class="task-shell-header-main">
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
|
|
45
|
+
<nav class="task-breadcrumb plugin-detail-breadcrumb" aria-label="Plugin breadcrumb">
|
|
46
|
+
<a class="task-breadcrumb-link" href="/plugins">Plugins</a>
|
|
47
|
+
<span class="task-breadcrumb-separator" aria-hidden="true">></span>
|
|
48
|
+
<a class="task-breadcrumb-link task-breadcrumb-current" href="<%= pluginDetailHref %>" aria-current="page"><%= plugin.title %></a>
|
|
49
|
+
</nav>
|
|
30
50
|
<div class="plugin-detail-title-row">
|
|
31
51
|
<% if (plugin.image) { %>
|
|
32
52
|
<img class="plugin-detail-title-art" src="<%= plugin.image %>" alt="<%= plugin.title %> icon">
|
|
@@ -48,16 +68,26 @@
|
|
|
48
68
|
</div>
|
|
49
69
|
<% } %>
|
|
50
70
|
</div>
|
|
71
|
+
<% if (showHeaderWebsite || canDeletePlugin) { %>
|
|
51
72
|
<div class="task-header-actions">
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<
|
|
73
|
+
<% if (showHeaderWebsite) { %>
|
|
74
|
+
<a class="task-link-button" href="<%= plugin.link %>" target="_blank" rel="noopener noreferrer">
|
|
75
|
+
<i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i>
|
|
76
|
+
<span>Website</span>
|
|
55
77
|
</a>
|
|
78
|
+
<% } %>
|
|
79
|
+
<% if (canDeletePlugin) { %>
|
|
80
|
+
<button class="task-button danger" type="button" data-plugin-delete aria-label="Delete <%= plugin.title %> plugin">
|
|
81
|
+
<i class="fa-solid fa-trash" aria-hidden="true"></i>
|
|
82
|
+
<span>Delete</span>
|
|
83
|
+
</button>
|
|
84
|
+
<% } %>
|
|
56
85
|
</div>
|
|
86
|
+
<% } %>
|
|
57
87
|
</header>
|
|
58
88
|
|
|
59
89
|
<div class="task-shell-body">
|
|
60
|
-
<div class="task-detail-layout">
|
|
90
|
+
<div class="task-detail-layout <%= pluginUi.showSidebar ? '' : 'task-detail-layout-single' %>">
|
|
61
91
|
<div class="task-detail-main">
|
|
62
92
|
<section class="task-section plugin-detail-actions-section" data-plugin-actions-section>
|
|
63
93
|
<div class="task-section-head">
|
|
@@ -160,19 +190,24 @@
|
|
|
160
190
|
<% } %>
|
|
161
191
|
</div>
|
|
162
192
|
|
|
193
|
+
<% if (pluginUi.showSidebar) { %>
|
|
163
194
|
<aside class="task-share-section task-detail-sidebar">
|
|
164
195
|
<div class="task-section-head">
|
|
165
196
|
<h2 class="task-section-title">Plugin status</h2>
|
|
166
197
|
</div>
|
|
167
198
|
<div class="task-side-stack">
|
|
168
|
-
<div class="
|
|
169
|
-
<div class="
|
|
170
|
-
<span class="
|
|
171
|
-
<span class="
|
|
199
|
+
<div class="plugin-detail-status-list">
|
|
200
|
+
<div class="plugin-detail-status-row">
|
|
201
|
+
<span class="plugin-detail-status-label"><%= pluginUi.sourceLabel %></span>
|
|
202
|
+
<span class="plugin-detail-status-value"><%= pluginUi.sourceValue %></span>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="plugin-detail-status-row">
|
|
205
|
+
<span class="plugin-detail-status-label"><%= pluginUi.statusLabel %></span>
|
|
206
|
+
<span class="plugin-detail-status-value"><%= pluginUi.statusValue %></span>
|
|
172
207
|
</div>
|
|
173
|
-
<div class="
|
|
174
|
-
<span class="
|
|
175
|
-
<span class="
|
|
208
|
+
<div class="plugin-detail-status-row">
|
|
209
|
+
<span class="plugin-detail-status-label"><%= pluginUi.githubPanelTitle %></span>
|
|
210
|
+
<span class="plugin-detail-status-value" data-plugin-share-note><%= githubStatusValue %></span>
|
|
176
211
|
</div>
|
|
177
212
|
</div>
|
|
178
213
|
<div class="task-actions task-detail-status-actions">
|
|
@@ -192,10 +227,6 @@
|
|
|
192
227
|
</div>
|
|
193
228
|
|
|
194
229
|
<section class="task-side-group">
|
|
195
|
-
<div class="task-section-head">
|
|
196
|
-
<h2 class="task-section-title"><%= pluginUi.githubPanelTitle %></h2>
|
|
197
|
-
<div class="task-section-note" data-plugin-share-note></div>
|
|
198
|
-
</div>
|
|
199
230
|
<% if (pluginUi.canManageSource) { %>
|
|
200
231
|
<div class="task-share-next-step-main">
|
|
201
232
|
<h3 class="task-share-next-step-title" data-plugin-share-next-title></h3>
|
|
@@ -224,12 +255,12 @@
|
|
|
224
255
|
</div>
|
|
225
256
|
</div>
|
|
226
257
|
</form>
|
|
227
|
-
<div class="task-actions plugin-share-static-actions">
|
|
258
|
+
<div class="task-actions plugin-share-static-actions <%= shareState.remoteWebUrl || (shareState.remoteUrl && shareState.githubConnected) ? '' : 'task-hidden' %>" data-plugin-share-static-actions>
|
|
228
259
|
<a class="task-link-button <%= shareState.remoteWebUrl ? '' : 'task-hidden' %>" href="<%= shareState.remoteWebUrl || '#' %>" target="_blank" rel="noopener noreferrer" data-plugin-share-remote-link>
|
|
229
260
|
<i class="fa-brands fa-github" aria-hidden="true"></i>
|
|
230
261
|
<span>View on GitHub</span>
|
|
231
262
|
</a>
|
|
232
|
-
<button class="task-button" type="button" data-plugin-share-refresh>
|
|
263
|
+
<button class="task-button <%= shareState.remoteUrl && shareState.githubConnected ? '' : 'task-hidden' %>" type="button" data-plugin-share-refresh>
|
|
233
264
|
<i class="fa-solid fa-rotate-right" aria-hidden="true"></i>
|
|
234
265
|
<span>Check again</span>
|
|
235
266
|
</button>
|
|
@@ -247,6 +278,7 @@
|
|
|
247
278
|
<% } %>
|
|
248
279
|
</section>
|
|
249
280
|
</aside>
|
|
281
|
+
<% } %>
|
|
250
282
|
</div>
|
|
251
283
|
</div>
|
|
252
284
|
</section>
|
package/server/views/plugins.ejs
CHANGED
|
@@ -869,12 +869,25 @@ body.dark {
|
|
|
869
869
|
<h1 class='task-title'>Plugins</h1>
|
|
870
870
|
<p class='task-description'>Open desktop editors externally or launch coding tools inside Pinokio.</p>
|
|
871
871
|
</div>
|
|
872
|
+
<div class="task-header-actions">
|
|
873
|
+
<button type="button" class="task-link-button primary" data-universal-launcher-open="create_plugin">
|
|
874
|
+
<i class="fa-solid fa-plus" aria-hidden="true"></i>
|
|
875
|
+
<span>Create plugin</span>
|
|
876
|
+
</button>
|
|
877
|
+
<button type="button" class="task-link-button" data-universal-launcher-open="create_plugin" data-universal-launcher-mode="download">
|
|
878
|
+
<i class="fa-solid fa-download" aria-hidden="true"></i>
|
|
879
|
+
<span>Download</span>
|
|
880
|
+
</button>
|
|
881
|
+
</div>
|
|
872
882
|
</header>
|
|
873
883
|
<div class='task-shell-body plugin-shell-body'>
|
|
874
884
|
<% if (plugins.length === 0) { %>
|
|
875
885
|
<div class='plugin-empty task-empty-state'>
|
|
876
886
|
<p>No plugins found. Clone or add plugin definitions under <code>~/pinokio/plugin</code> to see them listed here.</p>
|
|
877
|
-
<
|
|
887
|
+
<button type="button" class="task-button primary" data-universal-launcher-open="create_plugin" data-universal-launcher-mode="download">
|
|
888
|
+
<i class="fa-solid fa-download" aria-hidden="true"></i>
|
|
889
|
+
<span>Download plugins</span>
|
|
890
|
+
</button>
|
|
878
891
|
</div>
|
|
879
892
|
<% } else { %>
|
|
880
893
|
<div class='plugin-category-layout'>
|
|
@@ -1910,6 +1910,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1910
1910
|
payload.id = runId
|
|
1911
1911
|
payload.useId = true
|
|
1912
1912
|
}
|
|
1913
|
+
this.error = false
|
|
1914
|
+
this.eventPanelStopPending = false
|
|
1913
1915
|
this.resizeSync.reset()
|
|
1914
1916
|
this.socket.run(payload, async (packet) => {
|
|
1915
1917
|
if (packet.type === 'start') {
|
|
@@ -1973,6 +1975,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1973
1975
|
refreshParent(packet)
|
|
1974
1976
|
pluginTerminalDiscoveryRefresher.clear()
|
|
1975
1977
|
reloadMemory()
|
|
1978
|
+
if (this.eventPanelStopPending) {
|
|
1979
|
+
this.eventPanelStopPending = false
|
|
1980
|
+
postMessageToAncestors({
|
|
1981
|
+
e: "pinokio:event-panel-status",
|
|
1982
|
+
success: !this.error,
|
|
1983
|
+
status: "stopped"
|
|
1984
|
+
})
|
|
1985
|
+
}
|
|
1976
1986
|
this.flushPendingTerminalWrite()
|
|
1977
1987
|
this.term.write("\r\nDisconnected...\r\n")
|
|
1978
1988
|
document.querySelector("#status-window").innerHTML = "<b>Ready</b>"
|
|
@@ -2339,11 +2349,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
2339
2349
|
} else if (packet.type === "event") {
|
|
2340
2350
|
if (packet.data === "stop") {
|
|
2341
2351
|
if (window.__pinokioEventPanel) {
|
|
2342
|
-
|
|
2343
|
-
e: "pinokio:event-panel-status",
|
|
2344
|
-
success: !this.error,
|
|
2345
|
-
status: "stopped"
|
|
2346
|
-
})
|
|
2352
|
+
this.eventPanelStopPending = true
|
|
2347
2353
|
}
|
|
2348
2354
|
document.querySelector("#status-window").innerHTML = "<b>Ready</b>"
|
|
2349
2355
|
setTimeout(() => {
|
|
@@ -1153,6 +1153,33 @@ test("api.stop stops the canonical script path when the visible run id is decora
|
|
|
1153
1153
|
})
|
|
1154
1154
|
})
|
|
1155
1155
|
|
|
1156
|
+
test("api.stop disconnects when the script was deleted before stop cleanup", async () => {
|
|
1157
|
+
await withApiStopFixture(async ({ api, launchPath, killedGroups, stopped, packets }) => {
|
|
1158
|
+
const decoratedId = `${launchPath}?cwd=undefined`
|
|
1159
|
+
api.resolveScript = async () => {
|
|
1160
|
+
const error = new Error("missing script")
|
|
1161
|
+
error.code = "ENOENT"
|
|
1162
|
+
throw error
|
|
1163
|
+
}
|
|
1164
|
+
api.running[launchPath] = true
|
|
1165
|
+
api.running[decoratedId] = true
|
|
1166
|
+
api.kernel.memory.local[launchPath] = { live: true }
|
|
1167
|
+
api.kernel.memory.local[decoratedId] = { live: true }
|
|
1168
|
+
|
|
1169
|
+
await api.stop({ params: { id: decoratedId } })
|
|
1170
|
+
|
|
1171
|
+
assert.equal(api.running[launchPath], undefined)
|
|
1172
|
+
assert.equal(api.running[decoratedId], undefined)
|
|
1173
|
+
assert.equal(api.kernel.memory.local[launchPath], undefined)
|
|
1174
|
+
assert.equal(api.kernel.memory.local[decoratedId], undefined)
|
|
1175
|
+
assert.ok(killedGroups.includes(launchPath), "canonical script group must be killed")
|
|
1176
|
+
assert.ok(killedGroups.includes(decoratedId), "visible run id group must remain stopped")
|
|
1177
|
+
assert.equal(stopped.length, 1)
|
|
1178
|
+
assert.equal(stopped[0].scriptPath, launchPath)
|
|
1179
|
+
assert.ok(packets.some((packet) => packet.type === "disconnect" && packet.id === decoratedId))
|
|
1180
|
+
})
|
|
1181
|
+
})
|
|
1182
|
+
|
|
1156
1183
|
test("startup launch request does not block on its own startup status row", async () => {
|
|
1157
1184
|
await withFixtureApps({
|
|
1158
1185
|
target: {}
|