Fix workbench dark theme and enlarge dialogs

This commit is contained in:
Miayui
2026-09-18 09:11:59 +08:00
parent c812a1a595
commit e920a92505
18 changed files with 328 additions and 49 deletions
+3 -3
View File
@@ -5,7 +5,7 @@
inset: 0;
display: grid;
place-items: center;
padding: 68px 20px 20px;
padding: 16px;
background: color-mix(in oklch, var(--background) 58%, transparent);
backdrop-filter: blur(6px) saturate(.9);
-webkit-backdrop-filter: blur(6px) saturate(.9);
@@ -17,8 +17,8 @@
}
.console-v2 .energy-monitor-page {
width: min(1180px, 100%);
height: min(664px, 100%);
width: min(1480px, 100%);
height: min(900px, 100%);
min-height: 0;
display: grid;
grid-template-rows: auto minmax(0, 1fr);
@@ -4,7 +4,7 @@
inset: 0;
display: grid;
place-items: center;
padding: 68px 20px 20px;
padding: 16px;
background: color-mix(in oklch, var(--background) 58%, transparent);
backdrop-filter: blur(6px) saturate(.9);
-webkit-backdrop-filter: blur(6px) saturate(.9);
@@ -12,8 +12,8 @@
}
.console-v2 .firmware-workbench-layer[hidden] { display: none !important; }
.console-v2 .firmware-workbench-page {
width: min(1180px, 100%);
height: min(664px, 100%);
width: min(1480px, 100%);
height: min(900px, 100%);
min-height: 0;
display: grid;
grid-template-rows: 76px minmax(0, 1fr);
+20 -1
View File
@@ -3,6 +3,17 @@
const state = { open: false, returnFocus: null, backgroundInert: [] };
function currentWorkbenchTheme() {
return document.documentElement.dataset.glassTheme === "light" ? "light" : "dark";
}
function syncWorkbenchTheme(frame) {
frame?.contentWindow?.postMessage({
type: "cognitive-agent:theme-change",
theme: currentWorkbenchTheme(),
}, window.location.origin);
}
function setBackgroundInert(inert) {
const layer = document.querySelector("#firmwareWorkbenchLayer");
if (!layer) return;
@@ -80,11 +91,19 @@
</div>
<button id="firmwareWorkbenchClose" type="button" aria-label="关闭座椅固件开发工作台" title="关闭"><i data-lucide="x"></i></button>
</header>
<iframe class="firmware-workbench-frame" src="/firmware-workbench.html?embedded=1" title="座椅固件开发工作台"></iframe>
<iframe class="firmware-workbench-frame" title="座椅固件开发工作台"></iframe>
</section>`;
dock.append(trigger);
document.body.append(layer);
const frame = document.querySelector(".firmware-workbench-frame", layer);
frame.src = `/firmware-workbench.html?embedded=1&theme=${currentWorkbenchTheme()}`;
frame.addEventListener("load", () => syncWorkbenchTheme(frame));
window.addEventListener("cognitive-agent:theme-change", () => syncWorkbenchTheme(frame));
new MutationObserver(() => syncWorkbenchTheme(frame)).observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-glass-theme"],
});
trigger.addEventListener("click", () => setOpen(!state.open));
document.querySelector("#firmwareWorkbenchClose", layer).addEventListener("click", () => setOpen(false));
layer.addEventListener("click", (event) => { if (event.target === layer) setOpen(false); });
@@ -0,0 +1,65 @@
(() => {
"use strict";
const STORAGE_KEY = "cognitive-agent.glass-theme";
function normalizeTheme(value) {
return value === "light" ? "light" : value === "dark" ? "dark" : "";
}
function themeFromCookie() {
try {
return normalizeTheme(document.cookie
.split(";")
.map((part) => part.trim())
.find((part) => part.startsWith(`${STORAGE_KEY}=`))
?.slice(STORAGE_KEY.length + 1));
} catch (_error) {
return "";
}
}
function resolveInitialTheme() {
const requested = normalizeTheme(new URLSearchParams(window.location.search).get("theme"));
if (requested) return requested;
try {
const parentTheme = normalizeTheme(window.parent?.document?.documentElement?.dataset?.glassTheme);
if (parentTheme) return parentTheme;
} catch (_error) {
// Standalone and cross-origin rendering continue with local preferences.
}
try {
const stored = normalizeTheme(localStorage.getItem(STORAGE_KEY));
if (stored) return stored;
} catch (_error) {
// Storage may be unavailable in hardened browser contexts.
}
return themeFromCookie() || "dark";
}
function applyTheme(theme) {
const normalized = normalizeTheme(theme) || "dark";
document.documentElement.dataset.glassTheme = normalized;
document.documentElement.style.colorScheme = normalized;
document.querySelector("#firmwareWorkbenchThemeColor")
?.setAttribute("content", normalized === "dark" ? "#0f1526" : "#f3f6fb");
return normalized;
}
applyTheme(resolveInitialTheme());
window.addEventListener("storage", (event) => {
if (event.key === STORAGE_KEY) applyTheme(event.newValue);
});
window.addEventListener("message", (event) => {
if (event.origin !== window.location.origin) return;
if (window.parent !== window && event.source !== window.parent) return;
if (event.data?.type !== "cognitive-agent:theme-change") return;
applyTheme(event.data.theme);
});
window.CognitiveAgentFirmwareWorkbenchTheme = Object.freeze({
apply: applyTheme,
current: () => document.documentElement.dataset.glassTheme,
});
})();
+153 -1
View File
@@ -341,7 +341,7 @@ th:nth-child(4) { width: 28%; } th:nth-child(5) { width: 8%; } th:nth-child(6) {
.modal-backdrop { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; padding: 24px; background: rgba(31, 43, 61, .34); backdrop-filter: blur(4px); }
.modal-backdrop[hidden] { display: none; }
.modal { width: min(780px, 100%); max-height: min(680px, calc(100dvh - 48px)); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); }
.modal { width: min(1040px, 100%); max-height: min(820px, calc(100dvh - 48px)); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); }
.modal header, .modal footer { padding: 14px 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px; border-bottom: 1px solid var(--line); }
.modal footer { justify-content: flex-end; border-top: 1px solid var(--line); border-bottom: 0; }
.modal-body { overflow: auto; padding: 16px; }
@@ -454,3 +454,155 @@ body.embedded .file-cell span { line-height: 1.15; }
body.embedded .pipeline-card { overflow-x: auto; }
body.embedded .pipeline-card .pipeline { width: 680px; }
}
/* The workbench is rendered in an iframe, so it owns a complete theme token
set instead of relying on custom properties from the parent document. */
:root[data-glass-theme="dark"] {
color-scheme: dark;
--page: #090e1c;
--surface: #171e31;
--surface-soft: #11182a;
--line: #303a55;
--line-strong: #44516d;
--text: #edf2ff;
--muted: #9ba9c0;
--primary: #7aa3ff;
--primary-soft: #1b2b53;
--success: #55d4a1;
--success-soft: #12372d;
--warning: #f2bd68;
--danger: #ff8993;
--shadow: 0 26px 70px rgba(0, 0, 0, .42), 0 4px 18px rgba(0, 0, 0, .24);
}
:root[data-glass-theme="dark"] body:not(.embedded) {
background:
radial-gradient(circle at 15% 8%, color-mix(in srgb, var(--primary) 18%, transparent), transparent 31%),
linear-gradient(145deg, #11182b 0%, var(--page) 100%);
}
:root[data-glass-theme="dark"] body.embedded { background: transparent; }
:root[data-glass-theme="dark"] .shell,
:root[data-glass-theme="dark"] body.embedded .shell {
background: color-mix(in srgb, var(--surface-soft) 86%, var(--page));
border-color: color-mix(in srgb, var(--line-strong) 78%, transparent);
}
:root[data-glass-theme="dark"] .topbar {
background: color-mix(in srgb, var(--surface) 94%, transparent);
}
:root[data-glass-theme="dark"] :is(.back-link, .icon-button, .button-secondary) {
color: var(--muted);
background: var(--surface);
border-color: var(--line-strong);
}
:root[data-glass-theme="dark"] :is(.back-link, .icon-button):hover {
color: var(--primary);
border-color: color-mix(in srgb, var(--primary) 50%, var(--line));
background: var(--primary-soft);
}
:root[data-glass-theme="dark"] :is(.eyebrow, .section-kicker) { color: var(--muted); }
:root[data-glass-theme="dark"] :is(.environment-chip, .server-state) {
color: var(--muted);
background: var(--surface-soft);
}
:root[data-glass-theme="dark"] .server-state span { background: color-mix(in srgb, var(--muted) 72%, transparent); }
:root[data-glass-theme="dark"] .server-state.online,
:root[data-glass-theme="dark"] .status-badge[data-status="baseline"] {
border-color: color-mix(in srgb, var(--success) 44%, var(--line));
background: var(--success-soft);
}
:root[data-glass-theme="dark"] .card {
box-shadow: 0 2px 10px rgba(0, 0, 0, .16);
}
:root[data-glass-theme="dark"] .command-card > label { color: var(--muted); }
:root[data-glass-theme="dark"] textarea:focus { background: var(--surface); }
:root[data-glass-theme="dark"] :is(select, option) { color: var(--text); background: var(--surface); }
:root[data-glass-theme="dark"] .prompt-templates button,
:root[data-glass-theme="dark"] .cap-tags span,
:root[data-glass-theme="dark"] .table-actions :is(button, a) {
color: var(--primary);
background: var(--primary-soft);
border-color: color-mix(in srgb, var(--primary) 34%, var(--line));
}
:root[data-glass-theme="dark"] .capability-brief {
border-color: color-mix(in srgb, var(--primary) 25%, var(--line));
background: color-mix(in srgb, var(--primary-soft) 44%, var(--surface-soft));
}
:root[data-glass-theme="dark"] .capability-brief strong { color: var(--text); }
:root[data-glass-theme="dark"] .capability-brief > svg { color: var(--primary); }
:root[data-glass-theme="dark"] .pipeline-stage::after { background: var(--line); }
:root[data-glass-theme="dark"] .stage-node {
color: var(--muted);
border-color: var(--line-strong);
background: var(--surface);
}
:root[data-glass-theme="dark"] .pipeline-stage[data-status="success"] .stage-node {
border-color: color-mix(in srgb, var(--success) 62%, var(--line));
}
:root[data-glass-theme="dark"] .pipeline-stage[data-status="failed"] .stage-node,
:root[data-glass-theme="dark"] .pipeline-stage[data-status="blocked"] .stage-node,
:root[data-glass-theme="dark"] .release-result[data-state="failed"],
:root[data-glass-theme="dark"] .status-badge[data-status="failed"],
:root[data-glass-theme="dark"] .status-badge[data-status="blocked"] {
color: var(--danger);
border-color: color-mix(in srgb, var(--danger) 44%, var(--line));
background: color-mix(in srgb, var(--danger) 12%, var(--surface));
}
:root[data-glass-theme="dark"] .pipeline-stage[data-status="canceled"] .stage-node {
color: var(--muted);
background: var(--surface-soft);
}
:root[data-glass-theme="dark"] .pipeline-stage[data-status="pending_confirmation"] .stage-node,
:root[data-glass-theme="dark"] .status-badge[data-status="ready"],
:root[data-glass-theme="dark"] .status-badge[data-status="pending_confirmation"] {
color: var(--warning);
border-color: color-mix(in srgb, var(--warning) 44%, var(--line));
background: color-mix(in srgb, var(--warning) 12%, var(--surface));
}
:root[data-glass-theme="dark"] .pipeline-stage[data-status="success"]::after {
background: color-mix(in srgb, var(--success) 64%, var(--line));
}
:root[data-glass-theme="dark"] .release-result[data-state="success"],
:root[data-glass-theme="dark"] .status-badge[data-status="success"],
:root[data-glass-theme="dark"] .status-badge[data-status="published"] {
border-color: color-mix(in srgb, var(--success) 44%, var(--line));
background: var(--success-soft);
}
:root[data-glass-theme="dark"] .result-icon {
color: var(--muted);
background: color-mix(in srgb, var(--surface-soft) 78%, var(--line));
}
:root[data-glass-theme="dark"] .release-result[data-state="success"] .result-icon {
color: var(--success);
background: color-mix(in srgb, var(--success) 18%, var(--surface));
}
:root[data-glass-theme="dark"] .metrics div { border-color: var(--line); }
:root[data-glass-theme="dark"] :is(.log-stream, .log-details) { background: var(--surface-soft); }
:root[data-glass-theme="dark"] .empty-state svg { color: var(--muted); }
:root[data-glass-theme="dark"] .empty-state strong { color: var(--text); }
:root[data-glass-theme="dark"] .log-entry,
:root[data-glass-theme="dark"] :is(.change-item, .test-item) { border-color: var(--line); }
:root[data-glass-theme="dark"] .log-time { color: var(--muted); }
:root[data-glass-theme="dark"] .log-dot { background: var(--muted); }
:root[data-glass-theme="dark"] .log-copy p { color: var(--muted); }
:root[data-glass-theme="dark"] .inspector-tabs { background: var(--surface); }
:root[data-glass-theme="dark"] .inspector-tabs button { color: var(--muted); }
:root[data-glass-theme="dark"] .inspector-tabs button.active {
color: var(--primary);
background: var(--surface-soft);
}
:root[data-glass-theme="dark"] :is(.build-output, .code-block) { color: var(--text); }
:root[data-glass-theme="dark"] .server-target strong { color: var(--text); }
:root[data-glass-theme="dark"] th { color: var(--muted); background: var(--surface); }
:root[data-glass-theme="dark"] td { color: var(--muted); border-color: var(--line); }
:root[data-glass-theme="dark"] :is(.software-name strong, .file-cell strong) { color: var(--text); }
:root[data-glass-theme="dark"] .table-actions .delete-action {
color: var(--danger);
background: color-mix(in srgb, var(--danger) 12%, var(--surface));
}
:root[data-glass-theme="dark"] .modal-backdrop { background: rgba(2, 5, 14, .68); }
:root[data-glass-theme="dark"] .modal { background: var(--surface); }
:root[data-glass-theme="dark"] .diff-panel p { color: var(--muted); }
:root[data-glass-theme="dark"] .diff-panel.added {
border-color: color-mix(in srgb, var(--success) 42%, var(--line));
}
+4 -3
View File
@@ -3,11 +3,12 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="light" />
<meta name="theme-color" content="#f3f6fb" />
<meta name="color-scheme" content="light dark" />
<meta name="theme-color" content="#0f1526" id="firmwareWorkbenchThemeColor" />
<title>座椅固件开发工作台 · 511 工程</title>
<link rel="icon" href="/icons/app-icon-192.png" />
<link rel="stylesheet" href="/firmware-workbench.css?v=5" />
<script src="/firmware-workbench-theme.js?v=1"></script>
<link rel="stylesheet" href="/firmware-workbench.css?v=6" />
<script src="/vendor/lucide/0.468.0/lucide.min.js" defer></script>
<script src="/firmware-workbench.js?v=3" defer></script>
</head>
+2 -2
View File
@@ -33,7 +33,7 @@
document.documentElement.style.colorScheme = theme;
})();
</script>
<link rel="stylesheet" href="/firmware-workbench-entry.css?v=1" />
<link rel="stylesheet" href="/firmware-workbench-entry.css?v=2" />
<script src="/vendor/lucide/0.468.0/lucide.min.js" defer></script>
<script src="/vendor/three/0.147.0/three.min.js" defer></script>
<script src="/vendor/three/0.147.0/fflate.min.js" defer></script>
@@ -47,7 +47,7 @@
<script src="/self-extension.js?v=pet-settings-53-performance" defer></script>
<script src="/assistant-chat.js?v=codex-assistant-34" defer></script>
<script src="/energy-monitor.js?v=energy-monitor-5-performance" defer></script>
<script src="/firmware-workbench-entry.js?v=2" defer></script>
<script src="/firmware-workbench-entry.js?v=3" defer></script>
</head>
<body class="console-v2">
<div id="app" aria-busy="true"></div>
+7 -7
View File
@@ -1493,7 +1493,7 @@ button.v2-extension-capability.preview {
/* Dialogs ---------------------------------------------------------------- */
.v2-extension-dialog {
width: min(650px, calc(100vw - 40px));
width: min(780px, calc(100vw - 32px));
max-height: calc(100dvh - 40px);
margin: auto;
padding: 0;
@@ -2307,7 +2307,7 @@ form > .v2-extension-primary {
/* GSCU1B TCP runtime controls ------------------------------------------- */
.v2-gscu-tcp-dialog {
width: min(720px, calc(100vw - 30px));
width: min(960px, calc(100vw - 30px));
}
.v2-gscu-status {
@@ -2934,9 +2934,9 @@ form > .v2-extension-primary {
}
.v2-nfc-dialog {
width: min(900px, calc(100vw - 28px));
max-width: 900px;
max-height: min(860px, calc(100dvh - 28px));
width: min(1180px, calc(100vw - 28px));
max-width: 1180px;
max-height: min(900px, calc(100dvh - 28px));
padding: 0;
overflow: auto;
color: #203d3d;
@@ -4596,8 +4596,8 @@ form > .v2-extension-primary {
}
.v2-pet-settings-dialog {
width: min(760px, calc(100vw - 32px));
height: min(760px, calc(100dvh - 32px));
width: min(980px, calc(100vw - 32px));
height: min(860px, calc(100dvh - 32px));
max-height: calc(100dvh - 32px);
overflow: hidden;
}
+8 -7
View File
@@ -1,32 +1,33 @@
const CACHE_VERSION = "cognitive-agent-pad-v322-n7-firmware-merge";
const CACHE_VERSION = "cognitive-agent-pad-v323-dialog-theme";
const SHELL_CACHE = `${CACHE_VERSION}-shell`;
const RUNTIME_CACHE = `${CACHE_VERSION}-runtime`;
const APP_SHELL = [
"/",
"/index.html",
"/styles.css?v=dual-seat-23",
"/styles.css?v=dual-seat-24-dialog-size",
"/network.js?v=android-pad-2",
"/app.js?v=dual-seat-145-n7-dispatch",
"/gesture-control.js?v=android-pad-9",
"/pwa.js?v=android-pad-3",
"/console-v2.css?v=delivery-state-69",
"/console-v2.js?v=local-first-77-performance",
"/self-extension.css?v=pet-settings-52",
"/self-extension.css?v=pet-settings-54-dialog-size",
"/self-extension.js?v=pet-settings-53-performance",
"/speech-input.css?v=sensevoice-7",
"/speech-input.js?v=sensevoice-13",
"/speech-audio-worklet.js?v=sensevoice-5",
"/assistant-chat.css?v=codex-assistant-29",
"/assistant-chat.js?v=codex-assistant-34",
"/energy-monitor.css?v=energy-monitor-4",
"/energy-monitor.css?v=energy-monitor-5-dialog-size",
"/energy-monitor.js?v=energy-monitor-5-performance",
"/ui-consistency.css?v=spatial-ui-8",
"/codepen-glass-theme.css?v=creative-cloud-6-performance",
"/vue-ui.js?v=vue-presentation-3",
"/firmware-workbench-entry.css?v=1",
"/firmware-workbench-entry.js?v=2",
"/firmware-workbench-entry.css?v=2",
"/firmware-workbench-entry.js?v=3",
"/firmware-workbench.html",
"/firmware-workbench.css?v=5",
"/firmware-workbench-theme.js?v=1",
"/firmware-workbench.css?v=6",
"/firmware-workbench.js?v=3",
"/assets/pets/self-extension-cat.png?v=3",
"/assets/pets/self-extension-cat-entrance.png?v=3",
+4 -3
View File
@@ -395,8 +395,9 @@ body.mode-editor-open {
}
.mode-gallery {
width: min(1080px, calc(100vw - 32px));
max-height: min(680px, calc(100dvh - 32px));
width: min(1320px, calc(100vw - 32px));
height: min(860px, calc(100dvh - 32px));
max-height: min(860px, calc(100dvh - 32px));
display: grid;
grid-template-rows: auto auto minmax(0, 1fr) auto;
gap: 12px;
@@ -863,7 +864,7 @@ body.mode-editor-open {
}
.mode-editor {
width: min(760px, calc(100vw - 28px));
width: min(1040px, calc(100vw - 28px));
height: min(900px, calc(100dvh - 28px));
max-height: calc(100dvh - 28px);
display: grid;
+1
View File
@@ -30,6 +30,7 @@ const runtimeFiles = [
"assistant-chat.js",
"energy-monitor.js",
"firmware-workbench-entry.js",
"firmware-workbench-theme.js",
"firmware-workbench.js",
"firmware-workbench.html",
"styles.css",