add status bar for plugin/capability status instead of message box

This commit is contained in:
SoftFever
2026-07-03 14:57:35 +08:00
parent e3c6ec309d
commit 6fd1176661
5 changed files with 208 additions and 49 deletions

View File

@@ -18,6 +18,9 @@
<body onLoad="OnInit()">
<div class="app">
<div class="toolbar">
<button id="open_terminal" class="ButtonStyleRegular ButtonTypeChoice left-btn">
Open Terminal
</button>
<button id="refresh_btn" class="ButtonStyleRegular ButtonTypeChoice">
Refresh
</button>
@@ -27,10 +30,10 @@
<span class="explore-menu-icon" aria-hidden="true"></span>
</button>
<button id="explore_btn" class="ButtonStyleConfirm ButtonTypeChoice explore-main-btn" type="button">
Browse plugins
Install plugin
</button>
<div id="exploreMenu" class="explore-menu" role="menu" hidden>
<button type="button" class="explore-menu-item" role="menuitem" data-install-action="explore">Browse plugins</button>
<button type="button" class="explore-menu-item" role="menuitem" data-install-action="explore">Install plugin</button>
<button type="button" class="explore-menu-item" role="menuitem" data-install-action="install-local">Install local plugin</button>
</div>
</div>
@@ -129,11 +132,9 @@
</main>
</div>
<div id="AcceptArea">
<button id="open_terminal" class="ButtonStyleRegular ButtonTypeChoice left-btn">
Open Terminal
</button>
<div id="close_btn" class="ButtonStyleRegular ButtonTypeChoice">Close</div>
<div id="statusBar" class="status-bar is-empty" role="status" aria-live="polite">
<span class="status-dot" aria-hidden="true"></span>
<span id="statusText" class="status-text"></span>
</div>
<div id="ctxMenu" class="ctx" hidden></div>

View File

@@ -1,7 +1,7 @@
const pluginsById = new Map();
const pluginInstallActions = {
"explore": {
label: "Browse plugins",
label: "Install plugin",
command: "open_plugin_hub"
},
"install-local": {
@@ -40,7 +40,6 @@ function OnInit() {
exploreMenu?.addEventListener("click", OnExploreMenuClick);
document.getElementById("open_terminal")?.addEventListener("click", () => SendMessage("open_terminal"));
document.getElementById("detailUpdateBtn")?.addEventListener("click", UpdateSelectedPlugin);
document.getElementById("close_btn")?.addEventListener("click", () => SendMessage("close_page"));
document.querySelectorAll("[role='tab']").forEach((tab) => {
tab.addEventListener("click", () => ActivateDetailTab(String(tab.dataset.tab || "")));
@@ -216,9 +215,26 @@ function HandleStudio(value) {
if (payload.command === "list_plugins") {
SetSelectedInstallAction(payload.install_action, false);
ApplyPlugins(payload.data || []);
} else if (payload.command === "status_message") {
ShowStatusMessage(String(payload.message || ""), String(payload.level || "info"));
}
}
// Renders the latest plugin/capability operation result in the footer status bar. The result
// persists until the next operation replaces it; the native side already localizes the text.
function ShowStatusMessage(message, level) {
const bar = document.getElementById("statusBar");
const text = document.getElementById("statusText");
if (!bar || !text)
return;
const normalizedLevel = ["success", "warn", "error", "info"].includes(level) ? level : "info";
text.textContent = message;
text.title = message;
bar.classList.remove("is-empty", "level-success", "level-warn", "level-error", "level-info");
bar.classList.add(`level-${normalizedLevel}`);
}
function SafeJsonParse(value) {
try {
return JSON.parse(value);

View File

@@ -65,9 +65,22 @@ body {
gap: 8px;
}
/* Compact toolbar buttons */
.toolbar .ButtonTypeChoice {
height: 26px !important;
line-height: 25px !important;
font-size: 13px !important;
}
/* Only the plain buttons (Open Terminal, Refresh) tighten horizontal padding; the explore dropdown
buttons (grandchildren) keep their own padding/width. */
.toolbar > .ButtonTypeChoice {
padding: 0 10px !important;
}
.explore-dropdown {
--explore-arrow-width: 26px;
--explore-action-width: 160px;
--explore-arrow-width: 22px;
--explore-action-width: 140px;
position: relative;
display: inline-flex;
align-items: stretch;
@@ -652,8 +665,68 @@ body {
}
}
#AcceptArea {
/* Footer status bar: single-line, fixed-height strip that shows the latest script run result.
Reuses the shared status color tokens so it themes (light/dark) like the plugin status chips. */
.status-bar {
flex: 0 0 auto;
display: flex;
align-items: center;
gap: 8px;
min-height: 28px;
padding: 6px 14px;
box-sizing: border-box;
border-top: 1px solid var(--border);
background: var(--panel);
color: var(--text);
font-size: 13px;
}
.status-dot {
flex: 0 0 auto;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--muted);
}
.status-text {
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
/* Idle (no run yet): keep the strip height stable but hide the indicator dot. */
.status-bar.is-empty .status-dot {
visibility: hidden;
}
.status-bar.level-success .status-dot {
background: var(--plugin-status-ok);
}
.status-bar.level-success .status-text {
color: var(--plugin-status-ok);
}
.status-bar.level-error .status-dot {
background: var(--plugin-status-danger);
}
.status-bar.level-error .status-text {
color: var(--plugin-status-danger);
}
.status-bar.level-warn .status-dot {
background: var(--plugin-status-warn);
}
.status-bar.level-warn .status-text {
color: var(--plugin-status-warn);
}
.status-bar.level-info .status-dot {
background: var(--muted);
}
.ctx {