pinokiod 7.5.51 → 7.5.52
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/public/style.css +34 -0
- package/server/views/app.ejs +3 -1
- package/server/views/partials/home_server_popover_assets.ejs +3 -0
- package/server/views/partials/main_sidebar.ejs +46 -1
- package/test/launch-settings-ui.test.js +19 -2
- package/test/main-sidebar.test.js +20 -0
package/package.json
CHANGED
package/server/public/style.css
CHANGED
|
@@ -1530,6 +1530,40 @@ body.main-sidebar-page aside.main-sidebar .tab.selected .main-sidebar-action-ico
|
|
|
1530
1530
|
white-space: nowrap;
|
|
1531
1531
|
word-wrap: normal !important;
|
|
1532
1532
|
}
|
|
1533
|
+
.main-sidebar .main-sidebar-status-badge {
|
|
1534
|
+
grid-column: 3;
|
|
1535
|
+
justify-self: end;
|
|
1536
|
+
min-width: 28px;
|
|
1537
|
+
height: 15px;
|
|
1538
|
+
padding: 0 5px;
|
|
1539
|
+
box-sizing: border-box;
|
|
1540
|
+
border-radius: 999px;
|
|
1541
|
+
display: inline-flex;
|
|
1542
|
+
align-items: center;
|
|
1543
|
+
justify-content: center;
|
|
1544
|
+
background: rgba(15, 23, 42, 0.07);
|
|
1545
|
+
color: rgba(31, 41, 55, 0.6);
|
|
1546
|
+
font-size: 9px;
|
|
1547
|
+
font-weight: 700;
|
|
1548
|
+
line-height: 1;
|
|
1549
|
+
letter-spacing: 0;
|
|
1550
|
+
white-space: nowrap;
|
|
1551
|
+
}
|
|
1552
|
+
.main-sidebar .main-sidebar-status-badge[hidden] {
|
|
1553
|
+
display: none !important;
|
|
1554
|
+
}
|
|
1555
|
+
.main-sidebar .main-sidebar-status-badge[data-state="on"] {
|
|
1556
|
+
background: rgba(45, 180, 92, 0.14);
|
|
1557
|
+
color: #247a43;
|
|
1558
|
+
}
|
|
1559
|
+
body.dark .main-sidebar .main-sidebar-status-badge {
|
|
1560
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1561
|
+
color: rgba(229, 231, 235, 0.68);
|
|
1562
|
+
}
|
|
1563
|
+
body.dark .main-sidebar .main-sidebar-status-badge[data-state="on"] {
|
|
1564
|
+
background: rgba(74, 222, 128, 0.14);
|
|
1565
|
+
color: #86efac;
|
|
1566
|
+
}
|
|
1533
1567
|
.main-sidebar .tab.submenu {
|
|
1534
1568
|
padding-left: 14px !important;
|
|
1535
1569
|
}
|
package/server/views/app.ejs
CHANGED
|
@@ -16623,8 +16623,10 @@ const rerenderMenuSection = (container, html) => {
|
|
|
16623
16623
|
})
|
|
16624
16624
|
aside.addEventListener("pointerleave", closePeekSoon)
|
|
16625
16625
|
aside.addEventListener("focusout", closePeekSoon)
|
|
16626
|
-
aside.addEventListener("click", () => {
|
|
16626
|
+
aside.addEventListener("click", (event) => {
|
|
16627
16627
|
if (!isPeeking()) return
|
|
16628
|
+
const target = event.target
|
|
16629
|
+
if (target && target.closest && target.closest(".reveal, .revealer, [data-app-autolaunch-button]")) return
|
|
16628
16630
|
window.setTimeout(() => setPeeking(false), 0)
|
|
16629
16631
|
})
|
|
16630
16632
|
document.addEventListener("pointerdown", (event) => {
|
|
@@ -999,6 +999,9 @@ body.dark .home-server-popover__qr-close:focus-visible {
|
|
|
999
999
|
const render = (data) => {
|
|
1000
1000
|
const status = data && data.status ? data.status : "off"
|
|
1001
1001
|
setStatus(status)
|
|
1002
|
+
document.dispatchEvent(new CustomEvent("pinokio:home-server-status", {
|
|
1003
|
+
detail: { status, payload: data || { status } }
|
|
1004
|
+
}))
|
|
1002
1005
|
if (!panel) {
|
|
1003
1006
|
return
|
|
1004
1007
|
}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
<div class='main-sidebar-section' aria-label="Configure">
|
|
37
37
|
<div class="main-sidebar-section-title">Configure</div>
|
|
38
|
-
<a href="/network" class="tab <%= sidebarSelected === 'network' ? 'selected' : '' %>"><i class="fa-solid fa-wifi"></i><div class='caption'>Home Server</div></a>
|
|
38
|
+
<a href="/network" class="tab <%= sidebarSelected === 'network' ? 'selected' : '' %>" data-main-sidebar-home-server-tab><i class="fa-solid fa-wifi"></i><div class='caption'>Home Server</div><span class="main-sidebar-status-badge" data-main-sidebar-home-server-status aria-hidden="true" hidden></span></a>
|
|
39
39
|
<a class="tab <%= sidebarSelected === 'autolaunch' ? 'selected' : '' %>" href="/autolaunch"><i class="fa-solid fa-power-off"></i><div class='caption'>Autolaunch</div></a>
|
|
40
40
|
<a href="/connect" class="tab <%= sidebarSelected === 'connect' ? 'selected' : '' %>"><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
|
|
41
41
|
<a class="tab <%= sidebarSelected === 'settings' ? 'selected' : '' %>" href="/home?mode=settings"><i class="fa-solid fa-gear"></i><div class='caption'>Settings</div></a>
|
|
@@ -49,6 +49,51 @@
|
|
|
49
49
|
const headerToggle = document.getElementById("minimize-header");
|
|
50
50
|
const sidebar = document.getElementById("main-sidebar");
|
|
51
51
|
const peekTrigger = document.querySelector("[data-main-sidebar-peek-trigger]");
|
|
52
|
+
|
|
53
|
+
const initHomeServerStatusBadge = () => {
|
|
54
|
+
if (!sidebar || window.__pinokioMainSidebarHomeServerStatusInit) return;
|
|
55
|
+
const homeServerTab = sidebar.querySelector("[data-main-sidebar-home-server-tab]");
|
|
56
|
+
const homeServerBadge = sidebar.querySelector("[data-main-sidebar-home-server-status]");
|
|
57
|
+
if (!homeServerTab || !homeServerBadge) return;
|
|
58
|
+
|
|
59
|
+
window.__pinokioMainSidebarHomeServerStatusInit = true;
|
|
60
|
+
|
|
61
|
+
const renderHomeServerStatus = (data) => {
|
|
62
|
+
const status = data && data.status ? String(data.status) : "off";
|
|
63
|
+
const badgeState = status === "on" ? "on" : "off";
|
|
64
|
+
const label = badgeState === "on" ? "ON" : "OFF";
|
|
65
|
+
homeServerBadge.textContent = label;
|
|
66
|
+
homeServerBadge.hidden = false;
|
|
67
|
+
homeServerBadge.dataset.state = badgeState;
|
|
68
|
+
homeServerTab.dataset.homeServerStatus = badgeState;
|
|
69
|
+
homeServerTab.setAttribute("aria-label", `Home Server, ${label}`);
|
|
70
|
+
homeServerTab.setAttribute("title", `Home Server ${label}`);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
document.addEventListener("pinokio:home-server-status", (event) => {
|
|
74
|
+
const detail = event && event.detail ? event.detail : {};
|
|
75
|
+
renderHomeServerStatus(detail.payload || detail);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
fetch("/info/home-server", { cache: "no-store" })
|
|
79
|
+
.then((response) => {
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(`Home Server status failed: ${response.status}`);
|
|
82
|
+
}
|
|
83
|
+
return response.json();
|
|
84
|
+
})
|
|
85
|
+
.then(renderHomeServerStatus)
|
|
86
|
+
.catch(() => {
|
|
87
|
+
homeServerBadge.hidden = true;
|
|
88
|
+
delete homeServerBadge.dataset.state;
|
|
89
|
+
delete homeServerTab.dataset.homeServerStatus;
|
|
90
|
+
homeServerTab.removeAttribute("aria-label");
|
|
91
|
+
homeServerTab.removeAttribute("title");
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
initHomeServerStatusBadge();
|
|
96
|
+
|
|
52
97
|
if (body && sidebar && headerToggle && !headerToggle.dataset.mainSidebarHeaderToggle) {
|
|
53
98
|
headerToggle.dataset.mainSidebarHeaderToggle = "true";
|
|
54
99
|
headerToggle.classList.add("sidebar-toggle", "main-sidebar-header-toggle");
|
|
@@ -848,7 +848,7 @@ test("static guard: collapsed idle run page peeks without persisting sidebar sta
|
|
|
848
848
|
assert.match(appView, /const hasVisibleBrowserSurface = \(\) => \{[\s\S]*browserview\.querySelector\("iframe:not\(\.hidden\)"\)[\s\S]*browserview-network-status[\s\S]*data-launch-requirements-status/)
|
|
849
849
|
assert.match(appView, /if \(shouldAutoPeekOnIdle && initialCollapsed && !hasVisibleBrowserSurface\(\)\) \{[\s\S]*setPeeking\(true\)/)
|
|
850
850
|
assert.match(appView, /setCollapsed\(initialCollapsed, \{ persist: false \}\)/)
|
|
851
|
-
assert.match(appView, /aside\.addEventListener\("click", \(\) => \{[\s\S]*window\.setTimeout\(\(\) => setPeeking\(false\), 0\)/)
|
|
851
|
+
assert.match(appView, /aside\.addEventListener\("click", \(event\) => \{[\s\S]*target\.closest\("\.reveal, \.revealer, \[data-app-autolaunch-button\]"\)[\s\S]*window\.setTimeout\(\(\) => setPeeking\(false\), 0\)/)
|
|
852
852
|
})
|
|
853
853
|
|
|
854
854
|
test("app sidebar auto-peeks on collapsed idle run page and dismisses after click", async () => {
|
|
@@ -868,7 +868,12 @@ test("app sidebar auto-peeks on collapsed idle run page and dismisses after clic
|
|
|
868
868
|
<button id="sidebar-toggle"></button>
|
|
869
869
|
<div class="appcanvas vertical">
|
|
870
870
|
<button type="button" data-app-sidebar-peek-trigger></button>
|
|
871
|
-
<aside id="app-sidebar"
|
|
871
|
+
<aside id="app-sidebar">
|
|
872
|
+
<button type="button" class="reveal" id="sidebar-reveal">Downloads</button>
|
|
873
|
+
<button type="button" class="revealer" id="sidebar-revealer">Changes</button>
|
|
874
|
+
<button type="button" data-app-autolaunch-button id="sidebar-autolaunch">Autolaunch</button>
|
|
875
|
+
<button type="button" id="sidebar-action">Start</button>
|
|
876
|
+
</aside>
|
|
872
877
|
<main class="browserview">${browserSurface}</main>
|
|
873
878
|
</div>
|
|
874
879
|
<div id="browserview-network-status" hidden></div>
|
|
@@ -901,6 +906,18 @@ test("app sidebar auto-peeks on collapsed idle run page and dismisses after clic
|
|
|
901
906
|
assert.equal(aside.getAttribute("aria-hidden"), "false")
|
|
902
907
|
assert.equal(dom.window.localStorage.getItem(storageKey), "1")
|
|
903
908
|
|
|
909
|
+
aside.querySelector("#sidebar-reveal").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
910
|
+
await wait(5)
|
|
911
|
+
assert.equal(appcanvas.classList.contains("sidebar-peeking"), true)
|
|
912
|
+
|
|
913
|
+
aside.querySelector("#sidebar-revealer").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
914
|
+
await wait(5)
|
|
915
|
+
assert.equal(appcanvas.classList.contains("sidebar-peeking"), true)
|
|
916
|
+
|
|
917
|
+
aside.querySelector("#sidebar-autolaunch").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
918
|
+
await wait(5)
|
|
919
|
+
assert.equal(appcanvas.classList.contains("sidebar-peeking"), true)
|
|
920
|
+
|
|
904
921
|
aside.querySelector("#sidebar-action").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
905
922
|
await wait(5)
|
|
906
923
|
|
|
@@ -21,11 +21,31 @@ test('main sidebar moves Home Server under Configure', async () => {
|
|
|
21
21
|
assert.ok(configureIndex < homeServerIndex)
|
|
22
22
|
assert.ok(homeServerIndex < autolaunchIndex)
|
|
23
23
|
assert.match(source, /href="\/network"[\s\S]*Home Server/)
|
|
24
|
+
assert.match(source, /data-main-sidebar-home-server-tab/)
|
|
25
|
+
assert.match(source, /data-main-sidebar-home-server-status/)
|
|
26
|
+
assert.match(source, /fetch\("\/info\/home-server", \{ cache: "no-store" \}\)/)
|
|
27
|
+
assert.match(source, /status === "on" \? "on" : "off"/)
|
|
24
28
|
assert.doesNotMatch(source, /aria-label="Computer"/)
|
|
25
29
|
assert.doesNotMatch(source, />This machine</)
|
|
26
30
|
assert.doesNotMatch(source, />Local network</)
|
|
27
31
|
})
|
|
28
32
|
|
|
33
|
+
test('main sidebar styles the Home Server ON/OFF badge in the tab status column', async () => {
|
|
34
|
+
const style = await fs.readFile(path.resolve(__dirname, '..', 'server', 'public', 'style.css'), 'utf8')
|
|
35
|
+
const badgeRule = style.match(/\.main-sidebar \.main-sidebar-status-badge \{[\s\S]*?\n\}/)?.[0] || ''
|
|
36
|
+
const darkBadgeRule = style.match(/body\.dark \.main-sidebar \.main-sidebar-status-badge \{[\s\S]*?\n\}/)?.[0] || ''
|
|
37
|
+
|
|
38
|
+
assert.match(style, /\.main-sidebar \.main-sidebar-status-badge \{/)
|
|
39
|
+
assert.match(style, /grid-column:\s*3/)
|
|
40
|
+
assert.match(style, /\.main-sidebar \.main-sidebar-status-badge\[hidden\]/)
|
|
41
|
+
assert.match(style, /\.main-sidebar \.main-sidebar-status-badge\[data-state="on"\]/)
|
|
42
|
+
assert.match(style, /body\.dark \.main-sidebar \.main-sidebar-status-badge\[data-state="on"\]/)
|
|
43
|
+
assert.match(badgeRule, /background:\s*rgba\(15,\s*23,\s*42,\s*0\.07\)/)
|
|
44
|
+
assert.match(darkBadgeRule, /background:\s*rgba\(255,\s*255,\s*255,\s*0\.08\)/)
|
|
45
|
+
assert.doesNotMatch(`${badgeRule}\n${darkBadgeRule}`, /rgba\(207,\s*69,\s*69,\s*0\.12\)/)
|
|
46
|
+
assert.doesNotMatch(`${badgeRule}\n${darkBadgeRule}`, /#fca5a5/)
|
|
47
|
+
})
|
|
48
|
+
|
|
29
49
|
test('main sidebar no longer renders peer rows or phone access modal', async () => {
|
|
30
50
|
const source = await fs.readFile(sidebarFile, 'utf8')
|
|
31
51
|
const style = await fs.readFile(path.resolve(__dirname, '..', 'server', 'public', 'style.css'), 'utf8')
|