Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions shell/plugins/bar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ Example `shell.json` (bar subtree only shown):

The `omarchy.indicators` widget loads individual bar indicators from `indicators/`. Omit `items` (or set it to an empty array) to show all indicators in the default order, or set `items` to a subset such as `["Dnd", "Reminder", "NightLight"]`. Set `alwaysShow` to `true` to keep inactive indicators visible instead of revealing them only on hover. Multiple `omarchy.indicators` instances are allowed, so different sections can show different subsets.

Indicators can also come from other installed plugins. An `items` entry may be an object naming the plugin and the QML file inside it:

```json
{ "id": "omarchy.indicators",
"items": ["Dnd", "NightLight", { "id": "Backup", "plugin": "my.org.backup", "source": "Indicator.qml" }] }
```

The file is a normal `BarIndicator`; `source` defaults to `Indicator.qml` and must stay inside the plugin directory. Any other keys of the entry are passed to the indicator as `settings`.

## Orientation

All widgets work in `top`, `bottom`, `left`, and `right` positions. Popups anchor on the side opposite the bar edge, sliding into the workspace. Vertical bars use 28px width; widgets that show text fall back to compact icon-only forms (e.g. `media` hides its scrolling label).
Expand Down
2 changes: 1 addition & 1 deletion shell/plugins/bar/widgets/Indicators.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"key": "items",
"type": "multiselect",
"label": "Indicators",
"description": "Choose which indicators this widget instance should show. Leave empty to show all indicators.",
"description": "Choose which indicators this widget instance should show. Leave empty to show all indicators. In shell.json an entry may also be an object {\"id\", \"plugin\", \"source\"} that loads the indicator QML from another installed plugin.",
"noSelectionText": "All indicators",
"placeholderText": "Search indicators...",
"emptyText": "No indicators",
Expand Down
28 changes: 27 additions & 1 deletion shell/plugins/bar/widgets/Indicators.qml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@ BarWidget {
return ""
}

// Resolve an items entry to the QML file that implements it. Plain entries
// are first-party indicators in ../indicators/<id>.qml. An entry such as
// { "id": "Backup", "plugin": "my.org.backup", "source": "Indicator.qml" }
// loads <source> (default Indicator.qml) from that installed plugin's
// directory, looked up in the shell's plugin registry, so a plugin can ship
// its own BarIndicator without forking this widget. No "..", no absolute
// paths, and an unknown plugin loads nothing.
function resolveIndicatorSource(entry) {
var id = entryId(entry)
if (!id) return ""
var settings = entrySettings(entry)
var plugin = settings.plugin ? String(settings.plugin) : ""
if (!plugin) return Qt.resolvedUrl("../indicators/" + id + ".qml")

var registry = bar && bar.shell ? bar.shell.pluginRegistry : null
if (registry) void registry.registryRevision // re-resolve after a rescan
var manifest = registry && registry.installedPlugins ? registry.installedPlugins[plugin] : null
var dir = manifest && manifest.__sourceDir ? String(manifest.__sourceDir).replace(/\/$/, "") : ""
var file = settings.source ? String(settings.source) : "Indicator.qml"
if (!dir || file.indexOf("..") !== -1 || file.charAt(0) === "/") {
console.warn("Indicators: cannot resolve indicator", id, "from plugin", plugin, "source", file)
return ""
}
return Util.fileUrl(dir + "/" + file)
}

function entrySettings(entry) {
if (!Util.isPlainObject(entry)) return {}
var copy = {}
Expand Down Expand Up @@ -431,7 +457,7 @@ BarWidget {
id: indicatorSource

anchors.fill: parent
source: indicatorSlot.indicatorId ? Qt.resolvedUrl("../indicators/" + indicatorSlot.indicatorId + ".qml") : ""
source: root.resolveIndicatorSource(indicatorSlot.entry)
onLoaded: {
indicatorSlot.injectProps()
indicatorSlot.syncActiveState()
Expand Down