nova-shell/shell/lock/LockWidgets.qml

177 lines
5.9 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Services.Mpris
import Quickshell.Services.Pipewire
import "../services" as S
import "../applets" as C
Item {
id: root
width: 280
opacity: 0
property real _slideX: 80
NumberAnimation on opacity {
to: 1
duration: 400
easing.type: Easing.OutCubic
}
NumberAnimation on _slideX {
to: 0
duration: 500
easing.type: Easing.OutCubic
}
transform: Translate {
x: root._slideX
}
implicitHeight: _widgetContent.implicitHeight
visible: _mprisCard.visible || _volumeCard.visible || _backlightCard.visible || _notifPills.visible
Column {
id: _widgetContent
width: parent.width
spacing: 12
// Notification pills
LockNotifPills {
id: _notifPills
anchors.horizontalCenter: parent.horizontalCenter
}
// Media widget
Rectangle {
id: _mprisCard
width: parent.width
height: _mprisContent.implicitHeight + 16
radius: S.Theme.radius + 2
color: Qt.rgba(S.Theme.base01.r, S.Theme.base01.g, S.Theme.base01.b, 0.7)
border.color: Qt.rgba(S.Theme.base03.r, S.Theme.base03.g, S.Theme.base03.b, 0.3)
border.width: 1
visible: (S.Modules.lock.mpris ?? true) && _mprisPlayer !== null
readonly property var _mprisPlayers: (Mpris.players.values ?? []).filter(p => p.trackTitle || p.playbackState === MprisPlaybackState.Playing || p.playbackState === MprisPlaybackState.Paused)
property int _playerIdx: 0
readonly property var _mprisPlayer: _mprisPlayers[_playerIdx] ?? _mprisPlayers[0] ?? null
readonly property bool _playing: _mprisPlayer?.playbackState === MprisPlaybackState.Playing
C.MprisApplet {
id: _mprisContent
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 8
player: _mprisCard._mprisPlayer
players: _mprisCard._mprisPlayers
playing: _mprisCard._playing
playerIdx: _mprisCard._playerIdx
accentColor: S.Theme.base0D
cachedArt: _mprisCard._mprisPlayer?.trackArtUrl ?? ""
onPlayerSwitched: idx => {
_mprisCard._playerIdx = idx;
}
}
}
// Volume widget
Rectangle {
id: _volumeCard
width: parent.width
height: _volumeContent.implicitHeight + 16
radius: S.Theme.radius + 2
color: Qt.rgba(S.Theme.base01.r, S.Theme.base01.g, S.Theme.base01.b, 0.7)
border.color: Qt.rgba(S.Theme.base03.r, S.Theme.base03.g, S.Theme.base03.b, 0.3)
border.width: 1
visible: (S.Modules.lock.volume ?? true) && Pipewire.defaultAudioSink !== null
PwObjectTracker {
objects: [Pipewire.defaultAudioSink]
}
C.VolumeApplet {
id: _volumeContent
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 8
sink: Pipewire.defaultAudioSink
sinkList: []
streamList: []
accentColor: S.Theme.base0E
}
}
// Brightness widget
Rectangle {
id: _backlightCard
width: parent.width
height: _backlightContent.implicitHeight + 8
radius: S.Theme.radius + 2
color: Qt.rgba(S.Theme.base01.r, S.Theme.base01.g, S.Theme.base01.b, 0.7)
border.color: Qt.rgba(S.Theme.base03.r, S.Theme.base03.g, S.Theme.base03.b, 0.3)
border.width: 1
visible: _blDev !== ""
property string _blDev: ""
property int _percent: 0
Process {
running: true
command: ["sh", "-c", "ls /sys/class/backlight/ 2>/dev/null | head -1"]
stdout: StdioCollector {
onStreamFinished: {
const dev = text.trim();
if (dev)
_backlightCard._blDev = "/sys/class/backlight/" + dev;
}
}
}
FileView {
id: _blCurrent
path: _backlightCard._blDev ? _backlightCard._blDev + "/brightness" : ""
watchChanges: true
onFileChanged: reload()
onLoaded: _backlightCard._updatePercent()
}
FileView {
id: _blMax
path: _backlightCard._blDev ? _backlightCard._blDev + "/max_brightness" : ""
onLoaded: _backlightCard._updatePercent()
}
function _updatePercent() {
const c = parseInt(_blCurrent.text());
const m = parseInt(_blMax.text());
if (m > 0)
_percent = Math.round((c / m) * 100);
}
Process {
id: _blAdj
property string cmd: ""
command: ["sh", "-c", cmd]
onRunningChanged: if (!running && cmd !== "")
_blCurrent.reload()
}
C.BacklightApplet {
id: _backlightContent
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 4
percent: _backlightCard._percent
accentColor: S.Theme.base0A
onSetPercent: pct => {
_blAdj.cmd = "light -S " + Math.round(Math.max(0, Math.min(100, pct)));
_blAdj.running = true;
}
}
}
}
}