Address momus review: fix icons, vertical layout, popup coordination

- Replace nerd font glyphs that were stripped during the initial widget
  writes with verified codepoints sourced from the JetBrains Mono Nerd
  Font cmap (cpu-64-bit, scale-balance, notification-clear-all, etc).
- systemStats now switches to a Column layout when the bar is vertical
  so the widget no longer overflows a 28px-wide side bar.
- Remove notificationCenter from defaults: it registers a notification
  server and would collide with the mako daemon Omarchy autostarts.
- PopupCard owns the popout coordinator lifecycle and delegates close to
  its widget owner when provided; calendar and media now pass owner.
- brightness debounces brightnessctl writes through a coalescing timer
  to avoid spawning a process per slider tick.
- audioPanel tracks unfiltered Pipewire sinks/streams via PwObjectTracker
  so audio metadata becomes available before filtering.
- ModuleSlot re-injects bar/moduleName/settings whenever the bar config
  serial changes so widget settings update live with bar.json.
- Guard null bar references in workspacesPro and systemStats components
  that are constructed before bar injection.
This commit is contained in:
Ryan Hughes
2026-05-14 02:21:47 -04:00
parent 221e0e1fcc
commit fe73986a01
13 changed files with 152 additions and 76 deletions
+24 -9
View File
@@ -18,21 +18,35 @@ Item {
readonly property var source: Pipewire.defaultAudioSource
readonly property var nodes: Pipewire.nodes ? Pipewire.nodes.values : []
readonly property var audioSinks: {
readonly property var candidateSinks: {
var list = []
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i]
if (node && node.isSink && !node.isStream && node.audio) list.push(node)
if (node && node.isSink && !node.isStream) list.push(node)
}
return list
}
readonly property var candidateStreams: {
var list = []
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i]
if (node && node.isStream && !node.isSink) list.push(node)
}
return list
}
readonly property var audioSinks: {
var list = []
for (var i = 0; i < candidateSinks.length; i++)
if (candidateSinks[i].audio) list.push(candidateSinks[i])
return list
}
readonly property var audioStreams: {
var list = []
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i]
if (node && node.isStream && !node.isSink && node.audio) list.push(node)
}
for (var i = 0; i < candidateStreams.length; i++)
if (candidateStreams[i].audio) list.push(candidateStreams[i])
return list
}
@@ -65,8 +79,9 @@ Item {
implicitWidth: button.implicitWidth
implicitHeight: button.implicitHeight
PwObjectTracker { objects: root.audioSinks }
PwObjectTracker { objects: root.audioStreams }
PwObjectTracker { objects: root.candidateSinks }
PwObjectTracker { objects: root.candidateStreams }
PwObjectTracker { objects: root.sink ? [root.sink] : [] }
Common.WidgetButton {
id: button
@@ -224,7 +239,7 @@ Item {
node.properties ? node.properties["device.icon-name"] : "",
node.properties ? node.properties["device.product.name"] : ""
].join(" ")).toLowerCase()
if (blob.indexOf("headphone") !== -1 || blob.indexOf("headset") !== -1) return ""
if (blob.indexOf("headphone") !== -1 || blob.indexOf("headset") !== -1) return "󰋋"
if (blob.indexOf("bluetooth") !== -1) return "󰂯"
if (blob.indexOf("hdmi") !== -1 || blob.indexOf("display") !== -1) return "󰍹"
return "󰓃"
@@ -41,7 +41,7 @@ Item {
if (!adapter) return ""
if (!adapter.enabled) return "󰂲"
if (connectedDevices.length > 0) return "󰂱"
return ""
return "󰂯"
}
visible: adapter !== null
@@ -92,7 +92,7 @@ Item {
Item { width: parent.width - 200; height: 1 }
Common.PillButton {
iconText: root.adapter && root.adapter.enabled ? "" : ""
iconText: root.adapter && root.adapter.enabled ? "󰂯" : "󰂲"
text: root.adapter && root.adapter.enabled ? "On" : "Off"
foreground: root.bar.foreground
horizontalPadding: 8
@@ -102,7 +102,7 @@ Item {
}
Common.PillButton {
iconText: ""
iconText: "󰂳"
foreground: root.bar.foreground
horizontalPadding: 8
verticalPadding: 4
@@ -120,7 +120,7 @@ Item {
required property var modelData
width: parent.width
iconText: modelData && modelData.connected ? "󰂱" : ""
iconText: modelData && modelData.connected ? "󰂱" : "󰂯"
text: {
var label = modelData ? (modelData.deviceName || modelData.name || modelData.address || "Device") : ""
if (modelData && modelData.batteryAvailable) label += " " + Math.round(modelData.battery * 100) + "%"
+20 -2
View File
@@ -35,11 +35,29 @@ Item {
if (!readProc.running) readProc.running = true
}
property int pendingPercent: -1
function setBrightness(percent) {
var clamped = Math.max(1, Math.min(100, Math.round(percent)))
currentPercent = clamped
writeProc.command = ["bash", "-lc", "brightnessctl set " + clamped + "% >/dev/null"]
writeProc.running = true
pendingPercent = clamped
writeTimer.restart()
}
Timer {
id: writeTimer
interval: 60
repeat: false
onTriggered: {
if (writeProc.running) {
writeTimer.restart()
return
}
if (pendingPercent < 0) return
writeProc.command = ["bash", "-lc", "brightnessctl set " + pendingPercent + "% >/dev/null"]
pendingPercent = -1
writeProc.running = true
}
}
Component.onCompleted: refresh()
+3 -2
View File
@@ -68,6 +68,7 @@ Item {
id: popup
anchorItem: button
bar: root.bar
owner: root
open: root.popupOpen
contentWidth: 300
contentHeight: header.implicitHeight + grid.implicitHeight + 36
@@ -85,7 +86,7 @@ Item {
id: prevButton
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
iconText: ""
iconText: "󰅁"
foreground: root.bar.foreground
horizontalPadding: 8
verticalPadding: 4
@@ -105,7 +106,7 @@ Item {
id: nextButton
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
iconText: ""
iconText: "󰅂"
foreground: root.bar.foreground
horizontalPadding: 8
verticalPadding: 4
+6 -5
View File
@@ -28,7 +28,7 @@ Item {
}
readonly property bool hasMedia: activePlayer !== null && (activePlayer.trackTitle || activePlayer.trackArtist)
readonly property string playIcon: activePlayer && activePlayer.isPlaying ? "" : ""
readonly property string playIcon: activePlayer && activePlayer.isPlaying ? "󰏤" : "󰐊"
readonly property string title: activePlayer ? (activePlayer.trackTitle || "") : ""
readonly property string artist: activePlayer ? (activePlayer.trackArtist || "") : ""
@@ -118,6 +118,7 @@ Item {
id: popup
anchorItem: root
bar: root.bar
owner: root
open: root.popupOpen
contentWidth: 320
contentHeight: column.implicitHeight + 28
@@ -151,7 +152,7 @@ Item {
Text {
anchors.centerIn: parent
visible: !root.activePlayer || !root.activePlayer.trackArtUrl
text: ""
text: "󰝚"
color: root.bar.foreground
font.family: root.bar.fontFamily
font.pixelSize: 28
@@ -199,7 +200,7 @@ Item {
spacing: 6
Common.PillButton {
iconText: ""
iconText: "󰒮"
foreground: root.bar.foreground
horizontalPadding: 10
verticalPadding: 6
@@ -209,7 +210,7 @@ Item {
}
Common.PillButton {
iconText: root.activePlayer && root.activePlayer.isPlaying ? "" : ""
iconText: root.activePlayer && root.activePlayer.isPlaying ? "󰏤" : "󰐊"
foreground: root.bar.foreground
horizontalPadding: 14
verticalPadding: 6
@@ -220,7 +221,7 @@ Item {
}
Common.PillButton {
iconText: ""
iconText: "󰒭"
foreground: root.bar.foreground
horizontalPadding: 10
verticalPadding: 6
@@ -149,7 +149,7 @@ Item {
}
Common.PillButton {
iconText: ""
iconText: "󰑐"
foreground: root.bar.foreground
horizontalPadding: 8
verticalPadding: 4
@@ -205,7 +205,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: ""
iconText: "󰖩"
text: "Open Wi-Fi manager"
foreground: root.bar.foreground
horizontalPadding: 10
@@ -20,7 +20,7 @@ Item {
readonly property string icon: {
if (dnd) return "󰂛"
if (count > 0) return "󱅫"
return ""
return "󰂚"
}
NotificationServer {
@@ -131,7 +131,7 @@ Item {
}
Common.PillButton {
iconText: ""
iconText: "󰎟"
foreground: root.bar.foreground
horizontalPadding: 8
verticalPadding: 4
@@ -196,7 +196,7 @@ Item {
Common.PillButton {
id: dismissBtn
iconText: ""
iconText: "󰅖"
foreground: root.bar.foreground
horizontalPadding: 4
verticalPadding: 0
+5 -5
View File
@@ -25,7 +25,7 @@ Item {
id: button
anchors.fill: parent
bar: root.bar
text: ""
text: "󰐥"
fontSize: 14
tooltipText: "Power menu"
onPressed: function() { root.popupOpen = !root.popupOpen }
@@ -54,7 +54,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: ""
iconText: "󰌾"
text: "Lock"
foreground: root.bar.foreground
horizontalPadding: 10
@@ -74,7 +74,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: ""
iconText: "󰍃"
text: "Log out"
foreground: root.bar.foreground
horizontalPadding: 10
@@ -84,7 +84,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: ""
iconText: "󰜉"
text: "Reboot"
foreground: root.bar.foreground
horizontalPadding: 10
@@ -94,7 +94,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: ""
iconText: "󰐥"
text: "Shut down"
foreground: root.bar.urgent
horizontalPadding: 10
+55 -22
View File
@@ -119,30 +119,63 @@ Item {
}
}
implicitWidth: row.implicitWidth + 6
implicitHeight: bar ? bar.barSize : 26
readonly property bool vertical: bar ? bar.vertical : false
Row {
id: row
implicitWidth: vertical ? (bar ? bar.barSize : 28) : (statLayout.item ? statLayout.item.implicitWidth + 6 : 0)
implicitHeight: vertical ? (statLayout.item ? statLayout.item.implicitHeight + 6 : 0) : (bar ? bar.barSize : 26)
readonly property color statColor: bar ? bar.foreground : "#cacccc"
readonly property string statFont: bar ? bar.fontFamily : "JetBrainsMono Nerd Font"
Loader {
id: statLayout
anchors.centerIn: parent
spacing: 8
sourceComponent: root.vertical ? statColumn : statRow
}
StatPill {
glyph: "󰍛"
percent: root.cpuPercent
history: root.cpuHistory
vertical: root.bar.vertical
barFg: root.bar.foreground
fontFamily: root.bar.fontFamily
Component {
id: statRow
Row {
spacing: 8
StatPill {
glyph: "󰻠"
percent: root.cpuPercent
history: root.cpuHistory
vertical: false
barFg: root.statColor
fontFamily: root.statFont
}
StatPill {
glyph: "󰍛"
percent: root.memPercent
history: root.memHistory
vertical: false
barFg: root.statColor
fontFamily: root.statFont
}
}
}
StatPill {
glyph: ""
percent: root.memPercent
history: root.memHistory
vertical: root.bar.vertical
barFg: root.bar.foreground
fontFamily: root.bar.fontFamily
Component {
id: statColumn
Column {
spacing: 4
StatPill {
glyph: "󰻠"
percent: root.cpuPercent
history: root.cpuHistory
vertical: true
barFg: root.statColor
fontFamily: root.statFont
}
StatPill {
glyph: "󰍛"
percent: root.memPercent
history: root.memHistory
vertical: true
barFg: root.statColor
fontFamily: root.statFont
}
}
}
@@ -184,7 +217,7 @@ Item {
title: "CPU"
value: Math.round(root.cpuPercent) + "%"
history: root.cpuHistory
barFg: root.bar.foreground
barFg: root.statColor
fontFamily: root.bar.fontFamily
width: parent.width
}
@@ -193,7 +226,7 @@ Item {
title: "Memory"
value: Math.round(root.memPercent) + "%"
history: root.memHistory
barFg: root.bar.foreground
barFg: root.statColor
fontFamily: root.bar.fontFamily
width: parent.width
}
@@ -217,7 +250,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: "󰍛"
iconText: "󰆍"
text: "Open btop"
foreground: root.bar.foreground
horizontalPadding: 10
@@ -120,7 +120,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: ""
iconText: "󰑐"
text: "Refresh"
foreground: root.bar.foreground
horizontalPadding: 10
@@ -130,7 +130,7 @@ Item {
Common.PillButton {
width: parent.width
iconText: ""
iconText: "󰏌"
text: "Open wttr.in"
foreground: root.bar.foreground
horizontalPadding: 10