fix(schema): parse node-status banner and layout UI sections

The UI-schema loader walked a hardcoded list of flat TOML sections and
left [banners.*] and [layout] out, so those sections in ui.toml were
silently dropped. The node-status error strip at the top of the content
column could not be styled from the schema at all.

- The flat-section list is now one shared constant used by the file,
  string and overlay loaders, and it includes banners and layout.
- The node-status banner is themeable from ui.toml like every other
  section; a note in the toml records that these parse as flat sections.

No visible change unless ui.toml overrides those sections.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 08:23:30 -05:00
co-authored by Claude Opus 4.8
parent 8255923f33
commit 5376681af5
2 changed files with 14 additions and 18 deletions
+1
View File
@@ -700,6 +700,7 @@ status-pill-bg-alpha = { size = 30 }
status-pill-y-offset = { size = 1 }
confirmed-threshold = { size = 10 }
# NOTE: [banners.*] and [layout] are parsed as flat sections (kFlatSections in ui_schema.cpp).
# Persistent node/RPC error strip at the top of the content column (see App::renderNodeStatusBanner).
# Slightly taller than the per-tab sync banner so it comfortably holds the Reconnect/Restart action.
[banners.node-status]
+13 -18
View File
@@ -21,6 +21,16 @@ namespace dragonx {
namespace ui {
namespace schema {
namespace {
// 2-level sections (sectionName.elementName -> {style object}) shared by all loaders.
const char* const kFlatSections[] = {"business", "animations", "console",
"backdrop", "shutdown", "notifications", "status-bar",
"qr-code", "content-area", "style", "responsive",
"spacing", "spacing-tokens", "button", "dialog", "input", "fonts",
"inline-dialogs", "sidebar", "panels", "typography",
"effects", "security", "banners", "layout"};
} // namespace
// ============================================================================
// Singleton
// ============================================================================
@@ -81,12 +91,7 @@ bool UISchema::loadFromFile(const std::string& path) {
}
// Parse flat sections (2-level: sectionName.elementName → {style object})
for (const auto& flatSection : {"business", "animations", "console",
"backdrop", "shutdown", "notifications", "status-bar",
"qr-code", "content-area", "style", "responsive",
"spacing", "spacing-tokens", "button", "dialog", "input", "fonts",
"inline-dialogs", "sidebar", "panels", "typography",
"effects", "security"}) {
for (const char* flatSection : kFlatSections) {
if (auto* sec = root[flatSection].as_table()) {
parseFlatSection(static_cast<const void*>(sec), flatSection);
}
@@ -170,12 +175,7 @@ bool UISchema::loadFromString(const std::string& tomlStr, const std::string& lab
}
// Parse flat sections (2-level: sectionName.elementName → {style object})
for (const auto& flatSection : {"business", "animations", "console",
"backdrop", "shutdown", "notifications", "status-bar",
"qr-code", "content-area", "style", "responsive",
"spacing", "spacing-tokens", "button", "dialog", "input", "fonts",
"inline-dialogs", "sidebar", "panels", "typography",
"effects", "security"}) {
for (const char* flatSection : kFlatSections) {
if (auto* sec = root[flatSection].as_table()) {
parseFlatSection(static_cast<const void*>(sec), flatSection);
}
@@ -250,12 +250,7 @@ bool UISchema::mergeOverlayFromFile(const std::string& path) {
}
// Merge all flat sections (2-level)
for (const auto& flatSection : {"business", "animations", "console",
"backdrop", "shutdown", "notifications", "status-bar",
"qr-code", "content-area", "style", "responsive",
"spacing", "spacing-tokens", "button", "dialog", "input", "fonts",
"inline-dialogs", "sidebar", "panels", "typography",
"effects", "security"}) {
for (const char* flatSection : kFlatSections) {
if (auto* sec = root[flatSection].as_table()) {
parseFlatSection(static_cast<const void*>(sec), flatSection);
}