Skip to content

Fix dead widget when omarchy.notifications has been cloned - #9

Open
pabg92 wants to merge 1 commit into
Shavanced:mainfrom
pabg92:fix/resolve-cloned-notification-service
Open

Fix dead widget when omarchy.notifications has been cloned#9
pabg92 wants to merge 1 commit into
Shavanced:mainfrom
pabg92:fix/resolve-cloned-notification-service

Conversation

@pabg92

@pabg92 pabg92 commented Aug 27, 2026

Copy link
Copy Markdown

What

Resolve the notification service id through pluginRegistry.resolveEnabledId() before
handing it to firstPartyServiceFor(), instead of always asking for the literal
"omarchy.notifications".

Why

firstPartyServiceFor() is not a resolving lookup. In /usr/share/omarchy/shell/shell.qml
(lines 275-281) it is just:

function serviceFor(pluginId) {
  return _services[String(pluginId)] || null
}

function firstPartyServiceFor(pluginId) {
  return serviceFor(pluginId)
}

a raw dictionary read. And _syncServices() in the same file (~lines 325-340) only
instantiates services for plugins that are enabled, storing each one under its own
id (snext[key] = inst in ensureService).

omarchy plugin clone omarchy.notifications copies the built-in to <user>.<name>,
records omarchy.clonedFrom in the clone's manifest, enables the clone and disables the
original. So after a clone there is no _services["omarchy.notifications"] at all - the
service is registered under the clone's id.

The registry already has the answer: /usr/share/omarchy/shell/services/PluginRegistry.qml
lines 146-157, resolveEnabledId(id), whose own comment says "Callers keep using the
built-in id after cloning; the enabled local manifest is the implementation that should
receive the call."
It walks installedPlugins for an enabled manifest whose
omarchy.clonedFrom matches, and returns the requested id unchanged otherwise.

Who it affects

Anyone who has run omarchy plugin clone omarchy.notifications to customise the
notification service - a documented, first-class Omarchy workflow.

For them notificationService is null, so the widget silently degrades to an empty
shell: liveCount stays 0, historyDir is "" so no history rows are ever read,
dndSupported is false so the DND toggle is inert, and the icon never leaves its
idle glyph. Nothing is logged and no error is shown - it just looks like nothing
ever arrives.

Compatibility

Nothing changes for anyone who has not cloned: resolveEnabledId returns the id
unchanged, so the lookup is identical to today's. The binding also falls back to the
literal "omarchy.notifications" when the host exposes no pluginRegistry or no
resolveEnabledId, so older shells behave exactly as before.

It stays a readonly property binding rather than a one-shot function call, so it
re-evaluates when the registry populates or when a plugin is enabled/disabled at
runtime.

Found and verified on a real Omarchy 4.0.0 system (package 4.0.0-1), where the widget was dead until
this change.

firstPartyServiceFor() is a raw lookup into the shell's _services map, and
_syncServices() only registers a plugin under the id it is enabled under.
After `omarchy plugin clone omarchy.notifications` the clone is enabled as
<user>.<name> and the built-in is disabled, so the lookup returns null and
the widget goes dead: no live count, no history dir, and DND reports as
unsupported so the toggle does nothing.

PluginRegistry.resolveEnabledId() exists for this - it maps a built-in id
to whichever enabled manifest declares omarchy.clonedFrom for it, and
returns the id unchanged when nothing was cloned. Resolve through it first
and fall back to the literal id when the host has no registry.
@pabg92
pabg92 force-pushed the fix/resolve-cloned-notification-service branch from 740dc53 to f63e41e Compare August 27, 2026 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant