mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-25 03:42:05 +00:00
chore: UI Updates
This commit is contained in:
@@ -13,8 +13,7 @@
|
||||
<body>
|
||||
<main class="page">
|
||||
<header class="page-header">
|
||||
<h1 id="pageTitle" class="page-title">Plugin configuration</h1>
|
||||
<p id="pageSubtitle" class="page-subtitle"></p>
|
||||
<h1 id="pagePresetName" class="page-title"></h1>
|
||||
</header>
|
||||
|
||||
<div id="configEmpty" class="detail-empty">This preset does not use any plugin capabilities</div>
|
||||
@@ -24,9 +23,6 @@
|
||||
aria-label="Capabilities used by this preset"></div>
|
||||
<div class="config-view">
|
||||
<div id="configError" class="config-error" role="status" aria-live="polite" hidden></div>
|
||||
<div id="configMeta" class="config-meta" hidden>
|
||||
<span id="configSourceBadge" class="config-source-badge"></span>
|
||||
</div>
|
||||
<div id="configEditor" class="config-editor" hidden>
|
||||
<textarea id="configText" class="config-textarea thin-scroll" spellcheck="false"
|
||||
autocomplete="off" autocapitalize="off" aria-label="Capability configuration (JSON)"></textarea>
|
||||
|
||||
@@ -65,13 +65,9 @@ function ShowStatusMessage(message, level) {
|
||||
function ApplyCapabilities(payload) {
|
||||
capabilities = Array.isArray(payload.data) ? payload.data : [];
|
||||
|
||||
const title = document.getElementById("pageTitle");
|
||||
if (title)
|
||||
title.textContent = String(payload.title || "Plugin configuration");
|
||||
|
||||
const subtitle = document.getElementById("pageSubtitle");
|
||||
if (subtitle)
|
||||
subtitle.textContent = String(payload.preset_name || "");
|
||||
const presetName = document.getElementById("pagePresetName");
|
||||
if (presetName)
|
||||
presetName.textContent = String(payload.preset_name || "");
|
||||
|
||||
RenderCapabilities();
|
||||
}
|
||||
@@ -191,7 +187,6 @@ function ClearCapabilityConfigView() {
|
||||
const text = document.getElementById("configText");
|
||||
const error = document.getElementById("configError");
|
||||
const footer = document.getElementById("configFooter");
|
||||
const meta = document.getElementById("configMeta");
|
||||
|
||||
if (editor)
|
||||
editor.hidden = true;
|
||||
@@ -207,32 +202,23 @@ function ClearCapabilityConfigView() {
|
||||
}
|
||||
if (footer)
|
||||
footer.hidden = true;
|
||||
if (meta)
|
||||
meta.hidden = true;
|
||||
selectedHasPresetOverride = false;
|
||||
selectedReadOnly = false;
|
||||
SetConfigValidation("");
|
||||
}
|
||||
|
||||
function UpdateConfigMeta(payload) {
|
||||
// A read-only capability cannot be saved, and there is nothing to restore until the preset overrides
|
||||
// the global configuration.
|
||||
function UpdateConfigActions(payload) {
|
||||
selectedHasPresetOverride = payload?.has_preset_override === true;
|
||||
selectedReadOnly = payload?.read_only === true;
|
||||
|
||||
const meta = document.getElementById("configMeta");
|
||||
const badge = document.getElementById("configSourceBadge");
|
||||
const save = document.getElementById("configSaveBtn");
|
||||
const restore = document.getElementById("configRestoreBtn");
|
||||
if (!meta || !badge)
|
||||
return;
|
||||
|
||||
const source = String(payload?.source || "none");
|
||||
badge.textContent = source === "preset" ? "Preset override" :
|
||||
(source === "base" ? "Inherited from global configuration" : "No saved configuration");
|
||||
if (save)
|
||||
save.disabled = selectedReadOnly;
|
||||
if (restore)
|
||||
restore.disabled = selectedReadOnly || !selectedHasPresetOverride;
|
||||
meta.hidden = false;
|
||||
}
|
||||
|
||||
function ApplyCapabilityConfig(payload) {
|
||||
@@ -252,10 +238,13 @@ function ApplyCapabilityConfig(payload) {
|
||||
|
||||
const config = payload && Object.prototype.hasOwnProperty.call(payload, "config") ? payload.config : {};
|
||||
const html = String(payload?.custom_html || "");
|
||||
UpdateConfigMeta(payload);
|
||||
UpdateConfigActions(payload);
|
||||
|
||||
// Restore applies to either editor; Save and validation belong to the JSON editor only.
|
||||
ShowConfigFooter(!html);
|
||||
// The footer belongs to the JSON editor. A custom UI owns its whole surface, including whatever
|
||||
// save/restore controls it wants, and reaches the host through the window.orca bridge.
|
||||
const footer = document.getElementById("configFooter");
|
||||
if (footer)
|
||||
footer.hidden = html !== "";
|
||||
|
||||
if (html) {
|
||||
if (custom) {
|
||||
@@ -279,20 +268,6 @@ function ApplyCapabilityConfig(payload) {
|
||||
SetConfigValidation("");
|
||||
}
|
||||
|
||||
// withEditorControls is false for a custom UI, which saves through its own controls.
|
||||
function ShowConfigFooter(withEditorControls) {
|
||||
const footer = document.getElementById("configFooter");
|
||||
const save = document.getElementById("configSaveBtn");
|
||||
const validation = document.getElementById("configValidation");
|
||||
|
||||
if (footer)
|
||||
footer.hidden = false;
|
||||
if (save)
|
||||
save.hidden = !withEditorControls;
|
||||
if (validation)
|
||||
validation.hidden = !withEditorControls;
|
||||
}
|
||||
|
||||
function SetConfigValidation(message) {
|
||||
const node = document.getElementById("configValidation");
|
||||
const save = document.getElementById("configSaveBtn");
|
||||
@@ -379,8 +354,9 @@ function ApplyCapabilityConfigSaved(payload) {
|
||||
SetConfigValidation("");
|
||||
}
|
||||
|
||||
// The whole host surface a custom config UI gets: read the config, save one, be told when a save
|
||||
// lands. The frame is sandboxed into an opaque origin, so this bridge is its only channel.
|
||||
// The whole host surface a custom config UI gets: read the config, save one, drop the preset's
|
||||
// override, and be told when either lands. The frame is sandboxed into an opaque origin, so this
|
||||
// bridge is its only channel.
|
||||
function BuildCustomConfigDocument(html, config) {
|
||||
// Inlined into a <script>: a stored "</script>" would close the tag early, so escape "<" — the
|
||||
// literal stays valid JSON.
|
||||
@@ -392,6 +368,7 @@ function BuildCustomConfigDocument(html, config) {
|
||||
window.orca = {
|
||||
getConfig: function () { return current; },
|
||||
saveConfig: function (cfg) { parent.postMessage({ __orca: "save", config: cfg }, "*"); },
|
||||
restoreDefaults: function () { parent.postMessage({ __orca: "restore" }, "*"); },
|
||||
onConfig: function (cb) {
|
||||
if (typeof cb !== "function") return;
|
||||
handlers.push(cb);
|
||||
@@ -417,17 +394,21 @@ function OnCustomConfigMessage(event) {
|
||||
return;
|
||||
|
||||
const data = event.data;
|
||||
if (!data || data.__orca !== "save")
|
||||
return;
|
||||
if (!selectedPluginKey || !selectedCapabilityName)
|
||||
if (!data || !selectedPluginKey || !selectedCapabilityName)
|
||||
return;
|
||||
|
||||
SendMessage("save_capability_config", {
|
||||
plugin_key: selectedPluginKey,
|
||||
capability_name: selectedCapabilityName,
|
||||
capability_type: selectedCapabilityType,
|
||||
config: data.config === undefined ? {} : data.config
|
||||
});
|
||||
if (data.__orca === "save") {
|
||||
SendMessage("save_capability_config", {
|
||||
plugin_key: selectedPluginKey,
|
||||
capability_name: selectedCapabilityName,
|
||||
capability_type: selectedCapabilityType,
|
||||
config: data.config === undefined ? {} : data.config
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.__orca === "restore")
|
||||
RestoreCapabilityConfig();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
@@ -40,12 +40,6 @@ body {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
margin: 4px 0 0;
|
||||
font-size: 12px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* ---- Ported from resources/web/dialog/PluginsDialog/styles.css (Config tab) ---- */
|
||||
|
||||
.detail-empty {
|
||||
@@ -138,27 +132,6 @@ body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.config-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.config-meta[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.config-source-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 999px;
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.config-editor {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
@@ -157,8 +157,8 @@
|
||||
window.orca bridge. -->
|
||||
<iframe id="configCustom" class="config-custom" title="Plugin configuration"
|
||||
sandbox="allow-scripts" referrerpolicy="no-referrer" hidden></iframe>
|
||||
<!-- Host chrome for both editors: a custom UI needs Restore too, and keeping it here
|
||||
leaves it off the JS bridge. Save and validation are JSON-editor only. -->
|
||||
<!-- JSON-editor chrome only: a custom UI renders its own save/restore controls and
|
||||
drives them through the window.orca bridge. -->
|
||||
<div id="configFooter" class="config-view-footer" hidden>
|
||||
<span id="configValidation" class="config-validation" role="status" aria-live="polite"></span>
|
||||
<div class="config-actions">
|
||||
|
||||
@@ -975,8 +975,11 @@ function ApplyCapabilityConfig(payload) {
|
||||
const config = (payload && typeof payload.config === "object" && payload.config !== null) ? payload.config : {};
|
||||
const html = String(payload?.custom_html || "");
|
||||
|
||||
// Restore applies to either editor; Save and validation belong to the JSON editor only.
|
||||
ShowConfigFooter(!html);
|
||||
// The footer belongs to the JSON editor. A custom UI owns its whole surface, including whatever
|
||||
// save/restore controls it wants, and reaches the host through the window.orca bridge.
|
||||
const footer = document.getElementById("configFooter");
|
||||
if (footer)
|
||||
footer.hidden = html !== "";
|
||||
|
||||
if (html) {
|
||||
if (custom) {
|
||||
@@ -1000,20 +1003,6 @@ function ApplyCapabilityConfig(payload) {
|
||||
SetConfigValidation("");
|
||||
}
|
||||
|
||||
// withEditorControls is false for a custom UI, which saves through its own controls.
|
||||
function ShowConfigFooter(withEditorControls) {
|
||||
const footer = document.getElementById("configFooter");
|
||||
const save = document.getElementById("configSaveBtn");
|
||||
const validation = document.getElementById("configValidation");
|
||||
|
||||
if (footer)
|
||||
footer.hidden = false;
|
||||
if (save)
|
||||
save.hidden = !withEditorControls;
|
||||
if (validation)
|
||||
validation.hidden = !withEditorControls;
|
||||
}
|
||||
|
||||
function SetConfigValidation(message) {
|
||||
const node = document.getElementById("configValidation");
|
||||
const save = document.getElementById("configSaveBtn");
|
||||
@@ -1096,8 +1085,9 @@ function ApplyCapabilityConfigSaved(payload) {
|
||||
SetConfigValidation("");
|
||||
}
|
||||
|
||||
// The whole host surface a custom config UI gets: read the config, save one, be told when a save
|
||||
// lands. The frame is sandboxed into an opaque origin, so this bridge is its only channel.
|
||||
// The whole host surface a custom config UI gets: read the config, save one, restore the plugin's
|
||||
// defaults, and be told when either lands. The frame is sandboxed into an opaque origin, so this
|
||||
// bridge is its only channel.
|
||||
function BuildCustomConfigDocument(html, config) {
|
||||
// Inlined into a <script>: a stored "</script>" would close the tag early, so escape "<" — the
|
||||
// literal stays valid JSON.
|
||||
@@ -1109,6 +1099,7 @@ function BuildCustomConfigDocument(html, config) {
|
||||
window.orca = {
|
||||
getConfig: function () { return current; },
|
||||
saveConfig: function (cfg) { parent.postMessage({ __orca: "save", config: cfg }, "*"); },
|
||||
restoreDefaults: function () { parent.postMessage({ __orca: "restore" }, "*"); },
|
||||
onConfig: function (cb) {
|
||||
if (typeof cb !== "function") return;
|
||||
handlers.push(cb);
|
||||
@@ -1134,17 +1125,21 @@ function OnCustomConfigMessage(event) {
|
||||
return;
|
||||
|
||||
const data = event.data;
|
||||
if (!data || data.__orca !== "save")
|
||||
return;
|
||||
if (!selectedPluginId || !selectedCapabilityName)
|
||||
if (!data || !selectedPluginId || !selectedCapabilityName)
|
||||
return;
|
||||
|
||||
SendMessage("save_capability_config", {
|
||||
plugin_key: selectedPluginId,
|
||||
capability_name: selectedCapabilityName,
|
||||
capability_type: selectedCapabilityType,
|
||||
config: data.config === undefined ? {} : data.config
|
||||
});
|
||||
if (data.__orca === "save") {
|
||||
SendMessage("save_capability_config", {
|
||||
plugin_key: selectedPluginId,
|
||||
capability_name: selectedCapabilityName,
|
||||
capability_type: selectedCapabilityType,
|
||||
config: data.config === undefined ? {} : data.config
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.__orca === "restore")
|
||||
RestoreCapabilityConfig();
|
||||
}
|
||||
|
||||
function RenderThumbnail(plugin) {
|
||||
|
||||
Reference in New Issue
Block a user