Introduces a widgets/ directory of first-party QML modules and a common/ helpers library. Widgets auto-load by name from default/quickshell/bar/widgets/<name>.qml — no edits to shell.qml needed for additions beyond the firstPartyWidgets registry. New widgets (all orientation-aware, top/bottom/left/right): - media: MPRIS now-playing with scrolling label, cover art popup, play/pause/skip controls - audioPanel: master volume slider, output device picker, per-app mixer - networkPanel: Wi-Fi scan + connect, current connection details - bluetoothPanel: paired device list, connect/disconnect, battery - calendar: month grid popup keyed to today - notificationCenter: live notification feed, DND toggle, clear all - brightness: slider popup with scroll-to-adjust - powerProfile: power-saver/balanced/performance picker (UPower) - systemStats: inline CPU + RAM sparklines, expanded popup with btop - weatherFlyout: weather popup with refresh and full report - workspacesPro: animated focus indicator that slides between workspaces - powerMenu: lock/suspend/log out/reboot/shutdown popup - idleInhibitor: coffee-cup toggle wired to omarchy-toggle-idle - microphone: mic state + mute toggle + scroll volume Common helpers (default/quickshell/bar/common/): - WidgetButton: hover/press scale animation, tooltip integration - PopupCard: orientation-aware anchor + slide-in opacity transition - Slider: drag/wheel-able linear slider with knob hover bump - PillButton: rounded action button with icon + label Bar root gains requestPopout/releasePopout so only one popup is open at a time across widgets. Updates bar-defaults.json to ship the new widgets out of the box while keeping the legacy modules available.
57 lines
1.7 KiB
QML
57 lines
1.7 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Services.Pipewire
|
|
import "../common" as Common
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property QtObject bar: null
|
|
property string moduleName: "microphone"
|
|
property var settings: ({})
|
|
|
|
readonly property var source: Pipewire.defaultAudioSource
|
|
readonly property bool muted: source && source.audio ? source.audio.muted : true
|
|
readonly property real volume: source && source.audio ? source.audio.volume : 0
|
|
readonly property var nodes: Pipewire.nodes ? Pipewire.nodes.values : []
|
|
|
|
readonly property var activeStreams: {
|
|
var list = []
|
|
for (var i = 0; i < nodes.length; i++) {
|
|
var node = nodes[i]
|
|
if (node && node.isStream && node.isSink === false && !node.audio?.muted) list.push(node)
|
|
}
|
|
return list
|
|
}
|
|
|
|
readonly property bool inUse: activeStreams.length > 0 && !muted
|
|
|
|
visible: source !== null
|
|
implicitWidth: button.implicitWidth
|
|
implicitHeight: button.implicitHeight
|
|
|
|
function toggleMute() {
|
|
if (source && source.audio) source.audio.muted = !source.audio.muted
|
|
}
|
|
|
|
PwObjectTracker { objects: root.source ? [root.source] : [] }
|
|
|
|
Common.WidgetButton {
|
|
id: button
|
|
anchors.fill: parent
|
|
bar: root.bar
|
|
text: root.muted ? "" : ""
|
|
active: root.inUse
|
|
tooltipText: root.muted ? "Microphone muted" : (root.inUse ? "Microphone in use" : "Microphone live")
|
|
onPressed: function(b) {
|
|
if (b === Qt.MiddleButton) root.bar.run("omarchy-launch-audio")
|
|
else root.toggleMute()
|
|
}
|
|
onWheelMoved: function(delta) {
|
|
if (!root.source || !root.source.audio) return
|
|
var step = 0.05
|
|
root.source.audio.volume = Math.max(0, Math.min(1, root.volume + (delta > 0 ? step : -step)))
|
|
}
|
|
}
|
|
}
|