import QtQuick import QtQuick.Effects import Quickshell.Services.Pipewire import "." as M import "../services" as S M.BarModule { id: root spacing: S.Theme.moduleSpacing cursorShape: Qt.ArrowCursor readonly property bool _videoCapture: { if (!Pipewire.nodes) return false; for (const node of Pipewire.nodes.values) { if (!node.isStream) continue; const mc = node.properties?.["media.class"] ?? ""; if (mc === "Stream/Input/Video" || mc === "Stream/Output/Video") return true; } return false; } readonly property bool _audioIn: { if (!Pipewire.nodes) return false; for (const node of Pipewire.nodes.values) { if (!node.isStream) continue; const mc = node.properties?.["media.class"] ?? ""; if (mc === "Stream/Input/Audio") return true; } return false; } active: S.Modules.privacy.enable && (root._videoCapture || root._audioIn) // Screenshare indicator Text { visible: root._videoCapture text: "\uF03D" color: S.Theme.base08 font.pixelSize: S.Theme.fontSize + 2 font.family: S.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter layer.enabled: true layer.effect: MultiEffect { shadowEnabled: true shadowColor: S.Theme.base08 shadowBlur: 0.8 shadowVerticalOffset: 0 shadowHorizontalOffset: 0 } M.PulseAnimation on opacity { running: root._videoCapture halfDuration: 600 } } // Microphone indicator Text { visible: root._audioIn text: "\uF130" color: S.Theme.base0B font.pixelSize: S.Theme.fontSize + 2 font.family: S.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter layer.enabled: true layer.effect: MultiEffect { shadowEnabled: true shadowColor: S.Theme.base0B shadowBlur: 0.8 shadowVerticalOffset: 0 shadowHorizontalOffset: 0 } M.PulseAnimation on opacity { running: root._audioIn halfDuration: 600 } } }