pinokiod 7.5.51 → 7.5.53
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 +29 -18
- 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 +59 -4
- 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
|
@@ -85,7 +85,7 @@ body.app-page > header.navheader h1 > .home-server-popover {
|
|
|
85
85
|
}
|
|
86
86
|
.app-header-info {
|
|
87
87
|
position: relative;
|
|
88
|
-
flex:
|
|
88
|
+
flex: 0 1 auto;
|
|
89
89
|
min-width: 0;
|
|
90
90
|
display: inline-flex;
|
|
91
91
|
align-items: center;
|
|
@@ -100,8 +100,7 @@ body.app-page > header.navheader h1 > .home-server-popover {
|
|
|
100
100
|
align-items: center;
|
|
101
101
|
gap: 8px;
|
|
102
102
|
min-width: 0;
|
|
103
|
-
width:
|
|
104
|
-
max-width: none;
|
|
103
|
+
max-width: min(260px, 32vw);
|
|
105
104
|
height: 22px;
|
|
106
105
|
padding: 0 4px;
|
|
107
106
|
margin: 0 -4px;
|
|
@@ -325,11 +324,20 @@ body.app-page header.navheader .nav-labeled-action:focus-visible {
|
|
|
325
324
|
color: var(--pinokio-sidebar-tab-active-color);
|
|
326
325
|
}
|
|
327
326
|
@media only screen and (max-width: 1180px) {
|
|
328
|
-
body.app-page header.navheader .app-header-identity
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
327
|
+
body.app-page header.navheader .app-header-identity {
|
|
328
|
+
gap: 5px;
|
|
329
|
+
padding: 0 9px;
|
|
330
|
+
margin-right: 6px;
|
|
331
|
+
}
|
|
332
|
+
body.app-page header.navheader .app-header-info-trigger {
|
|
333
|
+
gap: 6px;
|
|
334
|
+
}
|
|
335
|
+
body.app-page header.navheader .resource-usage-trigger {
|
|
336
|
+
gap: 4px;
|
|
337
|
+
padding: 0 3px;
|
|
338
|
+
}
|
|
339
|
+
body.app-page header.navheader .resource-chip {
|
|
340
|
+
font-size: 10px;
|
|
333
341
|
}
|
|
334
342
|
}
|
|
335
343
|
.resource-usage {
|
|
@@ -6884,10 +6892,10 @@ header.navheader h1 {
|
|
|
6884
6892
|
min-width: 0;
|
|
6885
6893
|
display: flex;
|
|
6886
6894
|
align-items: center;
|
|
6887
|
-
justify-content:
|
|
6895
|
+
justify-content: center;
|
|
6888
6896
|
align-content: center;
|
|
6889
6897
|
flex-wrap: wrap;
|
|
6890
|
-
gap: 2px
|
|
6898
|
+
gap: 2px 8px;
|
|
6891
6899
|
min-height: 38px;
|
|
6892
6900
|
padding: 2px 9px;
|
|
6893
6901
|
border-radius: 999px;
|
|
@@ -6901,11 +6909,11 @@ header.navheader h1 {
|
|
|
6901
6909
|
background: rgba(255,255,255,0.06);
|
|
6902
6910
|
}
|
|
6903
6911
|
.mobile-bottom-nav .app-header-info {
|
|
6904
|
-
flex: 0 1
|
|
6905
|
-
max-width: 42
|
|
6912
|
+
flex: 0 1 auto;
|
|
6913
|
+
max-width: min(260px, 42%);
|
|
6906
6914
|
}
|
|
6907
6915
|
.mobile-bottom-nav .app-header-info-trigger {
|
|
6908
|
-
width:
|
|
6916
|
+
width: auto;
|
|
6909
6917
|
max-width: 100%;
|
|
6910
6918
|
height: auto;
|
|
6911
6919
|
min-height: 18px;
|
|
@@ -6976,14 +6984,15 @@ header.navheader h1 {
|
|
|
6976
6984
|
display: none;
|
|
6977
6985
|
}
|
|
6978
6986
|
.mobile-bottom-nav .resource-usage {
|
|
6979
|
-
flex:
|
|
6980
|
-
max-width:
|
|
6987
|
+
flex: 0 1 auto;
|
|
6988
|
+
max-width: 100%;
|
|
6981
6989
|
}
|
|
6982
6990
|
.mobile-bottom-nav .resource-usage-trigger {
|
|
6983
|
-
width:
|
|
6991
|
+
width: auto;
|
|
6992
|
+
max-width: 100%;
|
|
6984
6993
|
height: auto;
|
|
6985
6994
|
min-height: 0;
|
|
6986
|
-
justify-content:
|
|
6995
|
+
justify-content: center;
|
|
6987
6996
|
align-content: center;
|
|
6988
6997
|
flex-wrap: wrap;
|
|
6989
6998
|
gap: 2px 5px;
|
|
@@ -16623,8 +16632,10 @@ const rerenderMenuSection = (container, html) => {
|
|
|
16623
16632
|
})
|
|
16624
16633
|
aside.addEventListener("pointerleave", closePeekSoon)
|
|
16625
16634
|
aside.addEventListener("focusout", closePeekSoon)
|
|
16626
|
-
aside.addEventListener("click", () => {
|
|
16635
|
+
aside.addEventListener("click", (event) => {
|
|
16627
16636
|
if (!isPeeking()) return
|
|
16637
|
+
const target = event.target
|
|
16638
|
+
if (target && target.closest && target.closest(".reveal, .revealer, [data-app-autolaunch-button]")) return
|
|
16628
16639
|
window.setTimeout(() => setPeeking(false), 0)
|
|
16629
16640
|
})
|
|
16630
16641
|
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");
|
|
@@ -643,8 +643,23 @@ test("app navbar stays on one line when app identity and Home Server controls ar
|
|
|
643
643
|
assert.match(appView, /body\.app-page > header\.navheader h1 > \.home,[\s\S]*body\.app-page > header\.navheader h1 > \.home-server-popover\s*\{[\s\S]*flex:\s*0 0 auto;/)
|
|
644
644
|
assert.match(appView, /body\.app-page header\.navheader h1 > \.flexible\s*\{[\s\S]*flex:\s*0 0 0;[\s\S]*margin-left:\s*auto;/)
|
|
645
645
|
assert.match(appView, /\.app-header-identity\s*\{[\s\S]*flex:\s*1 1 auto;[\s\S]*max-width:\s*none;/)
|
|
646
|
+
assert.match(appView, /\.app-header-info\s*\{[\s\S]*flex:\s*0 1 auto;/)
|
|
647
|
+
const identityTriggerStart = appView.indexOf(".app-header-info-trigger {")
|
|
648
|
+
const identityTriggerEnd = appView.indexOf("\n}", identityTriggerStart)
|
|
649
|
+
const identityTriggerRule = identityTriggerStart >= 0 && identityTriggerEnd > identityTriggerStart
|
|
650
|
+
? appView.slice(identityTriggerStart, identityTriggerEnd)
|
|
651
|
+
: ""
|
|
652
|
+
assert.match(identityTriggerRule, /max-width:\s*min\(260px, 32vw\);/)
|
|
653
|
+
assert.doesNotMatch(identityTriggerRule, /width:\s*100%;/)
|
|
654
|
+
assert.doesNotMatch(identityTriggerRule, /max-width:\s*none;/)
|
|
646
655
|
assert.doesNotMatch(appView, /nav-action-label\s*\{[^}]*display:\s*none;/)
|
|
647
|
-
|
|
656
|
+
const compactRuleStart = appView.indexOf("@media only screen and (max-width: 1180px)")
|
|
657
|
+
const compactRuleEnd = appView.indexOf(".resource-usage {", compactRuleStart)
|
|
658
|
+
const compactHeaderRule = compactRuleStart >= 0 && compactRuleEnd > compactRuleStart
|
|
659
|
+
? appView.slice(compactRuleStart, compactRuleEnd)
|
|
660
|
+
: ""
|
|
661
|
+
assert.match(compactHeaderRule, /body\.app-page header\.navheader \.resource-usage-trigger\s*\{[\s\S]*gap:\s*4px;[\s\S]*padding:\s*0 3px;/)
|
|
662
|
+
assert.doesNotMatch(compactHeaderRule, /\.resource-chip--(?:cpu|ram|vram)[\s\S]*display:\s*none !important;/)
|
|
648
663
|
})
|
|
649
664
|
|
|
650
665
|
test("download page header does not show browser chrome controls", async () => {
|
|
@@ -848,7 +863,7 @@ test("static guard: collapsed idle run page peeks without persisting sidebar sta
|
|
|
848
863
|
assert.match(appView, /const hasVisibleBrowserSurface = \(\) => \{[\s\S]*browserview\.querySelector\("iframe:not\(\.hidden\)"\)[\s\S]*browserview-network-status[\s\S]*data-launch-requirements-status/)
|
|
849
864
|
assert.match(appView, /if \(shouldAutoPeekOnIdle && initialCollapsed && !hasVisibleBrowserSurface\(\)\) \{[\s\S]*setPeeking\(true\)/)
|
|
850
865
|
assert.match(appView, /setCollapsed\(initialCollapsed, \{ persist: false \}\)/)
|
|
851
|
-
assert.match(appView, /aside\.addEventListener\("click", \(\) => \{[\s\S]*window\.setTimeout\(\(\) => setPeeking\(false\), 0\)/)
|
|
866
|
+
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
867
|
})
|
|
853
868
|
|
|
854
869
|
test("app sidebar auto-peeks on collapsed idle run page and dismisses after click", async () => {
|
|
@@ -868,7 +883,12 @@ test("app sidebar auto-peeks on collapsed idle run page and dismisses after clic
|
|
|
868
883
|
<button id="sidebar-toggle"></button>
|
|
869
884
|
<div class="appcanvas vertical">
|
|
870
885
|
<button type="button" data-app-sidebar-peek-trigger></button>
|
|
871
|
-
<aside id="app-sidebar"
|
|
886
|
+
<aside id="app-sidebar">
|
|
887
|
+
<button type="button" class="reveal" id="sidebar-reveal">Downloads</button>
|
|
888
|
+
<button type="button" class="revealer" id="sidebar-revealer">Changes</button>
|
|
889
|
+
<button type="button" data-app-autolaunch-button id="sidebar-autolaunch">Autolaunch</button>
|
|
890
|
+
<button type="button" id="sidebar-action">Start</button>
|
|
891
|
+
</aside>
|
|
872
892
|
<main class="browserview">${browserSurface}</main>
|
|
873
893
|
</div>
|
|
874
894
|
<div id="browserview-network-status" hidden></div>
|
|
@@ -901,6 +921,18 @@ test("app sidebar auto-peeks on collapsed idle run page and dismisses after clic
|
|
|
901
921
|
assert.equal(aside.getAttribute("aria-hidden"), "false")
|
|
902
922
|
assert.equal(dom.window.localStorage.getItem(storageKey), "1")
|
|
903
923
|
|
|
924
|
+
aside.querySelector("#sidebar-reveal").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
925
|
+
await wait(5)
|
|
926
|
+
assert.equal(appcanvas.classList.contains("sidebar-peeking"), true)
|
|
927
|
+
|
|
928
|
+
aside.querySelector("#sidebar-revealer").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
929
|
+
await wait(5)
|
|
930
|
+
assert.equal(appcanvas.classList.contains("sidebar-peeking"), true)
|
|
931
|
+
|
|
932
|
+
aside.querySelector("#sidebar-autolaunch").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
933
|
+
await wait(5)
|
|
934
|
+
assert.equal(appcanvas.classList.contains("sidebar-peeking"), true)
|
|
935
|
+
|
|
904
936
|
aside.querySelector("#sidebar-action").dispatchEvent(new dom.window.MouseEvent("click", { bubbles: true }))
|
|
905
937
|
await wait(5)
|
|
906
938
|
|
|
@@ -953,7 +985,30 @@ test("app identity popover exposes launcher metadata and remote browser link", a
|
|
|
953
985
|
assert.match(appView, /window\.open\(href, "_blank"\)/)
|
|
954
986
|
assert.match(appView, /window\.open\(href, "_blank", "browser"\)/)
|
|
955
987
|
assert.match(appView, /No browser-openable remote detected/)
|
|
956
|
-
|
|
988
|
+
const cssRule = (selector) => {
|
|
989
|
+
const start = appView.indexOf(`${selector} {`)
|
|
990
|
+
if (start < 0) return ""
|
|
991
|
+
const tail = appView.slice(start)
|
|
992
|
+
const end = tail.match(/\n\s*\}/)
|
|
993
|
+
return end ? tail.slice(0, end.index + end[0].length) : ""
|
|
994
|
+
}
|
|
995
|
+
const mobileIdentityRule = cssRule(".mobile-bottom-nav__identity")
|
|
996
|
+
const mobileInfoRule = cssRule(".mobile-bottom-nav .app-header-info")
|
|
997
|
+
const mobileInfoTriggerRule = cssRule(".mobile-bottom-nav .app-header-info-trigger")
|
|
998
|
+
const mobileResourceRule = cssRule(".mobile-bottom-nav .resource-usage")
|
|
999
|
+
const mobileResourceTriggerRule = cssRule(".mobile-bottom-nav .resource-usage-trigger")
|
|
1000
|
+
assert.match(mobileIdentityRule, /justify-content:\s*center;/)
|
|
1001
|
+
assert.match(mobileIdentityRule, /overflow:\s*visible;/)
|
|
1002
|
+
assert.doesNotMatch(mobileIdentityRule, /justify-content:\s*flex-start;/)
|
|
1003
|
+
assert.match(mobileInfoRule, /flex:\s*0 1 auto;/)
|
|
1004
|
+
assert.match(mobileInfoRule, /max-width:\s*min\(260px, 42%\);/)
|
|
1005
|
+
assert.match(mobileInfoTriggerRule, /width:\s*auto;/)
|
|
1006
|
+
assert.doesNotMatch(mobileInfoTriggerRule, /(^|\n)\s*width:\s*100%;/)
|
|
1007
|
+
assert.match(mobileResourceRule, /flex:\s*0 1 auto;/)
|
|
1008
|
+
assert.match(mobileResourceRule, /max-width:\s*100%;/)
|
|
1009
|
+
assert.match(mobileResourceTriggerRule, /width:\s*auto;/)
|
|
1010
|
+
assert.match(mobileResourceTriggerRule, /justify-content:\s*center;/)
|
|
1011
|
+
assert.doesNotMatch(mobileResourceTriggerRule, /justify-content:\s*flex-start;/)
|
|
957
1012
|
assert.match(appView, /\.mobile-bottom-nav \.app-header-info-popover \{[\s\S]*bottom: calc\(100% \+ 9px\);[\s\S]*width: min\(390px, calc\(100vw - 24px\)\);/)
|
|
958
1013
|
assert.match(appView, /\.mobile-bottom-nav \.resource-usage-popover \{[\s\S]*bottom: calc\(100% \+ 9px\);/)
|
|
959
1014
|
assert.doesNotMatch(appView, /Open launcher remote/)
|
|
@@ -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')
|