From 952b33b9812f2d31211cd683508f7cb0478a6cff Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 22 May 2026 15:05:55 -0400 Subject: [PATCH] Make indicators customizable --- shell/plugins/bar/FirstPartyWidgets.qml | 13 ++++++++++++- shell/plugins/bar/README.md | 2 +- shell/plugins/bar/widgets/Indicators.qml | 7 ++++--- shell/plugins/settings/SettingsPanel.qml | 17 +++++++++++++++-- shell/shell-defaults.json | 9 +-------- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/shell/plugins/bar/FirstPartyWidgets.qml b/shell/plugins/bar/FirstPartyWidgets.qml index 7f1c8294..ac8cc70c 100644 --- a/shell/plugins/bar/FirstPartyWidgets.qml +++ b/shell/plugins/bar/FirstPartyWidgets.qml @@ -15,7 +15,17 @@ QtObject { "PowerPanel": { displayName: "Power", description: "Battery, power profile, and system stats", category: "System", allowMultiple: false, sourceDir: "../panels", sourceName: "Power" }, "BluetoothPanel": { displayName: "Bluetooth", description: "Bluetooth device list with connect/disconnect", category: "Network", allowMultiple: false, sourceDir: "../panels", sourceName: "Bluetooth" }, "Clock": { displayName: "Clock", description: "Day/time label; click to toggle alternate format", category: "Time", allowMultiple: false, settingsForm: "clockSettings" }, - "Indicators": { displayName: "Indicators", description: "Manual state indicators", category: "Status", allowMultiple: false }, + "Indicators": { displayName: "Indicators", description: "Manual state indicators", category: "Status", allowMultiple: true, + schema: [ + { key: "items", type: "multiselect", label: "Indicators", description: "Choose which indicators this widget instance should show. Leave empty to show all indicators.", noSelectionText: "All indicators", placeholderText: "Search indicators...", emptyText: "No indicators", + options: [ + { value: "Dnd", label: "Do not disturb", description: "Notification silencing" }, + { value: "NightLight", label: "Night light", description: "Blue-light filter" }, + { value: "StayAwake", label: "Stay awake", description: "Idle lock and screensaver override" }, + { value: "ScreenRecording", label: "Screen recording", description: "GPU screen recorder status" }, + { value: "Dictation", label: "Dictation", description: "Voice typing status" } + ] } + ] }, "NotificationCenter": { displayName: "Notification center", description: "Recent notifications + DND", category: "Status", allowMultiple: false }, "SystemUpdate": { displayName: "System update", description: "Indicates available system updates", category: "System", allowMultiple: false }, "SystemStats": { displayName: "System stats", description: "CPU icon — hover for graphs, click to open btop", category: "System", allowMultiple: false }, @@ -52,6 +62,7 @@ QtObject { category: meta.category || "Misc", allowMultiple: meta.allowMultiple === true, settingsForm: meta.settingsForm || "", + schema: Array.isArray(meta.schema) ? meta.schema : [], source: "first-party" } var comp = Qt.createComponent(url, Component.Asynchronous) diff --git a/shell/plugins/bar/README.md b/shell/plugins/bar/README.md index bfef7be7..22119a87 100644 --- a/shell/plugins/bar/README.md +++ b/shell/plugins/bar/README.md @@ -76,7 +76,7 @@ Example `shell.json` (bar subtree only shown): | `panels.bluetooth` | Bluetooth icon + popup with device list, connect/disconnect, battery | left = popup · right = toggle radio · middle = bluetoothctl TUI | | `panels.monitor` | Brightness and laptop display controls | left = popup | -The `Indicators` widget loads individual bar indicators from `indicators/`, ordered by its `items` array in `shell.json`. Rich panels such as `PowerPanel`, `NetworkPanel`, and `AudioPanel` live in `../panels/` above. +The `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", "NightLight"]`. Multiple `Indicators` instances are allowed, so different sections can show different subsets. Rich panels such as `PowerPanel`, `NetworkPanel`, and `AudioPanel` live in `../panels/` above. ## Orientation diff --git a/shell/plugins/bar/widgets/Indicators.qml b/shell/plugins/bar/widgets/Indicators.qml index d842b09c..bfd5bc02 100644 --- a/shell/plugins/bar/widgets/Indicators.qml +++ b/shell/plugins/bar/widgets/Indicators.qml @@ -9,6 +9,7 @@ BarWidget { moduleName: "Indicators" readonly property int indicatorSlotExtent: Style.space(22) + readonly property var defaultIndicatorEntries: [ "Dnd", "NightLight", "StayAwake", "ScreenRecording", "Dictation" ] readonly property int inactiveSlotExtent: indicatorEntries.length * indicatorSlotExtent readonly property var indicatorEntries: indicatorEntriesFromSettings(settings) property var activeIndicatorIds: [] @@ -41,9 +42,9 @@ BarWidget { } function indicatorEntriesFromSettings(settings) { - var source = [] - if (settings.items && typeof settings.items.length === "number") source = settings.items - else if (settings.indicators && typeof settings.indicators.length === "number") source = settings.indicators + var source = defaultIndicatorEntries + if (settings.items && typeof settings.items.length === "number" && settings.items.length > 0) source = settings.items + else if (settings.indicators && typeof settings.indicators.length === "number" && settings.indicators.length > 0) source = settings.indicators var result = [] for (var i = 0; i < source.length; i++) { diff --git a/shell/plugins/settings/SettingsPanel.qml b/shell/plugins/settings/SettingsPanel.qml index aa302e1e..146f6336 100644 --- a/shell/plugins/settings/SettingsPanel.qml +++ b/shell/plugins/settings/SettingsPanel.qml @@ -133,7 +133,7 @@ Item { left: [{ id: "Omarchy" }, { id: "Workspaces" }], center: [ { id: "Clock", format: "dddd HH:mm", formatAlt: "dd MMMM 'W'ww yyyy", verticalFormat: "HH\n\u2014\nmm" }, - { id: "Weather" }, { id: "Indicators", items: [ "Dnd", "NightLight", "StayAwake", "ScreenRecording", "Dictation" ] }, { id: "SystemUpdate" } + { id: "Weather" }, { id: "Indicators" }, { id: "SystemUpdate" } ], right: [ { id: "Tray" }, { id: "BluetoothPanel" }, { id: "NetworkPanel" }, @@ -281,8 +281,21 @@ Item { mutateSection(section, function(a) { a.splice(index, 1) }) } + function defaultEntryForWidget(id) { + var bar = defaultBarDraft() + var layout = bar && bar.layout ? bar.layout : {} + var sections = ["left", "center", "right"] + for (var s = 0; s < sections.length; s++) { + var entries = layout[sections[s]] || [] + for (var i = 0; i < entries.length; i++) { + if (entries[i].id === id) return Util.cloneJson(entries[i]) + } + } + return { id: id } + } + function addEntry(section, id) { - mutateSection(section, function(a) { a.push({ id: id }) }) + mutateSection(section, function(a) { a.push(defaultEntryForWidget(id)) }) } function updateEntry(section, index, newEntry) { diff --git a/shell/shell-defaults.json b/shell/shell-defaults.json index c018dd6b..08d086d9 100644 --- a/shell/shell-defaults.json +++ b/shell/shell-defaults.json @@ -28,14 +28,7 @@ "id": "Weather" }, { - "id": "Indicators", - "items": [ - "Dnd", - "NightLight", - "StayAwake", - "ScreenRecording", - "Dictation" - ] + "id": "Indicators" }, { "id": "SystemUpdate"