Load each bar widget's component once
Qt.createComponent is asynchronous, but a widget was only recorded in pluginWidgetComponents once its component finished. syncPluginWidgets runs several times while the shell starts, and every pass that ran while a load was still in flight could not tell it apart from one that had never happened — so it started a second load of the same URL. All twenty bar widgets were loaded twice. The duplicate component then replaced the first in the registry, and swapping a slot's component makes its Loader build the replacement before dropping the original. Both were briefly live, and both registered the widget's IPC handler, which is where the "another handler is registered for target" warnings came from. Claim the key when the load starts instead, and release it if the component fails so a later rescan can retry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e31355bbaf
commit
64810d815b
+22
-4
@@ -700,6 +700,12 @@ ShellRoot {
|
||||
source: "plugin"
|
||||
}
|
||||
|
||||
// A load already in flight for this URL registers itself when it
|
||||
// finishes. Starting a second one produces a second Component for the
|
||||
// same widget, and swapping a slot's component rebuilds its item —
|
||||
// briefly running two of the widget, each registering its IPC handler.
|
||||
if (existing && existing.url === url && !existing.component) continue
|
||||
|
||||
// If the component URL is unchanged, just refresh the metadata in
|
||||
// place. We can't skip this even when the URL matches: manifests can
|
||||
// change schema, defaults, or sourceDir between rescans, and the
|
||||
@@ -769,17 +775,29 @@ ShellRoot {
|
||||
}
|
||||
}
|
||||
|
||||
function setPluginWidgetComponent(registryKey, entry) {
|
||||
var next = ({})
|
||||
for (var k in pluginWidgetComponents) if (k !== registryKey) next[k] = pluginWidgetComponents[k]
|
||||
if (entry) next[registryKey] = entry
|
||||
pluginWidgetComponents = next
|
||||
}
|
||||
|
||||
function loadPluginWidget(registryKey, url, meta) {
|
||||
// Claim the key before the component exists. Qt.createComponent is
|
||||
// asynchronous and syncPluginWidgets runs several times while the shell
|
||||
// starts, so without a marker the later passes cannot tell a load in
|
||||
// flight from one that never happened.
|
||||
setPluginWidgetComponent(registryKey, { url: url, component: null })
|
||||
|
||||
var comp = Qt.createComponent(url, Component.Asynchronous)
|
||||
function finalize() {
|
||||
if (comp.status === Component.Ready) {
|
||||
shell.barWidgetRegistry.register(registryKey, comp, meta)
|
||||
var next = ({})
|
||||
for (var k in pluginWidgetComponents) next[k] = pluginWidgetComponents[k]
|
||||
next[registryKey] = { url: url, component: comp }
|
||||
pluginWidgetComponents = next
|
||||
shell.setPluginWidgetComponent(registryKey, { url: url, component: comp })
|
||||
} else if (comp.status === Component.Error) {
|
||||
console.warn("Plugin widget " + registryKey + " failed: " + comp.errorString())
|
||||
// Drop the claim so a later rescan can retry.
|
||||
shell.setPluginWidgetComponent(registryKey, null)
|
||||
shell.pluginRegistry.pluginLoadFailed(registryKey, comp.errorString())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user