diff --git a/resources/web/dialog/PluginsConfigDialog/index.js b/resources/web/dialog/PluginsConfigDialog/index.js index 3df85e0a33..c97263d3ac 100644 --- a/resources/web/dialog/PluginsConfigDialog/index.js +++ b/resources/web/dialog/PluginsConfigDialog/index.js @@ -9,10 +9,12 @@ let selectedCapabilityType = ""; let selectedHasPresetOverride = false; let selectedReadOnly = false; -// Identity of the capability whose custom UI is currently loaded in the frame. Saving re-sends the -// whole capability_config payload, and rebuilding the frame from it would reload the plugin's page -// under the user's cursor; when this still matches, the new values are posted in instead. -let customFrameKey = ""; +// Whether the frame holds the selected capability's custom UI. Payloads are gated by +// IsCurrentCapability and every selection change clears the view, so a loaded frame is always the +// selected capability's. Saving re-sends the whole capability_config payload, and rebuilding the +// frame from it would reload the plugin's page under the user's cursor; while the frame is loaded, +// the new values are posted in instead. +let customFrameLoaded = false; function SafeJsonParse(text) { try { @@ -173,10 +175,6 @@ function IsCurrentCapability(payload) { && String(payload?.capability_type || "") === selectedCapabilityType; } -function CapabilityKey(payload) { - return JSON.stringify([payload?.plugin_key, payload?.capability_name, payload?.capability_type]); -} - function RequestCapabilityConfig() { if (!selectedPluginKey || !selectedCapabilityName) return; @@ -202,7 +200,7 @@ function ClearCapabilityConfigView() { if (custom) { custom.hidden = true; custom.removeAttribute("srcdoc"); - customFrameKey = ""; + customFrameLoaded = false; } if (text) text.value = ""; @@ -260,10 +258,10 @@ function ApplyCapabilityConfig(payload) { if (custom) { const context = OrcaConfigContext(payload, "preset"); custom.hidden = false; - if (customFrameKey === CapabilityKey(payload) && custom.contentWindow) { + if (customFrameLoaded && custom.contentWindow) { custom.contentWindow.postMessage({ __orca: "config", config: config, context: context }, "*"); } else { - customFrameKey = CapabilityKey(payload); + customFrameLoaded = true; custom.srcdoc = BuildCustomConfigDocument(html, config, context); } } @@ -276,7 +274,7 @@ function ApplyCapabilityConfig(payload) { if (custom) { custom.hidden = true; custom.removeAttribute("srcdoc"); - customFrameKey = ""; + customFrameLoaded = false; } if (editor) editor.hidden = false; @@ -416,7 +414,7 @@ document.addEventListener("DOMContentLoaded", () => { // OnCustomConfigMessage matches on the frame's contentWindow, not the origin ("null" when // sandboxed), and ignores anything else. window.addEventListener("message", OnCustomConfigMessage); - OrcaWatchThemeForFrame(() => document.getElementById("configCustom")); + OrcaWatchThemeForFrame("configCustom"); SendMessage("request_capabilities"); }); diff --git a/resources/web/dialog/PluginsDialog/index.js b/resources/web/dialog/PluginsDialog/index.js index 036fc8552a..ea081a23aa 100644 --- a/resources/web/dialog/PluginsDialog/index.js +++ b/resources/web/dialog/PluginsDialog/index.js @@ -90,7 +90,7 @@ function OnInit() { // OnCustomConfigMessage matches on the frame's contentWindow, not the origin ("null" when // sandboxed), and ignores anything else. window.addEventListener("message", OnCustomConfigMessage); - OrcaWatchThemeForFrame(() => document.getElementById("configCustom")); + OrcaWatchThemeForFrame("configCustom"); document.addEventListener("click", (event) => { if (!event.target.closest(".ctx")) diff --git a/resources/web/dialog/js/plugin-config-ui.js b/resources/web/dialog/js/plugin-config-ui.js index 0f16c0c48c..5dfd47fc96 100644 --- a/resources/web/dialog/js/plugin-config-ui.js +++ b/resources/web/dialog/js/plugin-config-ui.js @@ -3,41 +3,25 @@ // opaque origin, so this bridge is its only channel, and both must offer plugin authors exactly the // same one — hence a single module rather than a copy per dialog. -// The host theme "contract" (WebViewHostDialog::host_theme_vars_css). The document-start injector -// stamps it on the top-level page only — it returns early in child frames — so a sandboxed config UI -// never sees it unless we hand it over. -const ORCA_THEME_VARS = [ - "--orca-bg", - "--orca-fg", - "--orca-muted", - "--orca-border", - "--orca-accent", - "--orca-accent-fg", - "--orca-font" -]; - -// Read the contract off this page as it is rendering right now, so the frame always opens in the -// live theme rather than whatever the app started in. +// The host theme "contract" (WebViewHostDialog::host_theme_vars_css) arrives as a complete +// ":root{--orca-*;color-scheme:...}" rule in the injected