qs: add TempNotification

This commit is contained in:
2026-04-20 17:49:13 +02:00
parent 8562298d83
commit 266ea92f4a
8 changed files with 168 additions and 16 deletions
@@ -1,28 +1,102 @@
import QtQuick import QtQuick
import QtQuick.Layouts
import Quickshell.Io import Quickshell.Io
import qs.Components
import qs.Constants import qs.Constants
import qs.Services import qs.Services
Text { Item {
text: TimeService.time + " | " + TimeService.dateString id: root
font.pointSize: Style.fontSizeM
font.family: Fonts.primary
color: Colors.mPrimary
MouseArea { readonly property int switchDistance: Style.barHeight
anchors.fill: parent readonly property int animationDuration: Style.animationNormal
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor implicitWidth: Math.max(timeLayer.implicitWidth, notiLayer.implicitWidth)
onClicked: { implicitHeight: Math.max(timeLayer.implicitHeight, notiLayer.implicitHeight)
action.running = !action.running; clip: true
UText {
id: timeLayer
readonly property real restY: (root.height - implicitHeight) / 2
anchors.horizontalCenter: parent.horizontalCenter
y: TempNotificationService.active ? restY + root.switchDistance : restY
opacity: TempNotificationService.active ? 0 : 1
text: TimeService.time + " | " + TimeService.dateString
color: Colors.mPrimary
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
onClicked: {
action.running = !action.running;
}
} }
Process {
id: action
running: false
command: ["vicinae", "toggle"]
}
Behavior on y {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.OutCubic
}
}
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.OutCubic
}
}
} }
Process { RowLayout {
id: action id: notiLayer
readonly property real restY: (root.height - implicitHeight) / 2
anchors.horizontalCenter: parent.horizontalCenter
y: TempNotificationService.active ? restY : restY - root.switchDistance
opacity: TempNotificationService.active ? 1 : 0
spacing: Style.marginXS
UIcon {
visible: TempNotificationService.iconName !== ""
iconName: TempNotificationService.iconName
color: Colors.mPrimary
}
UText {
text: TempNotificationService.message
color: Colors.mPrimary
}
Behavior on y {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.OutCubic
}
}
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.OutCubic
}
}
running: false
command: ["vicinae", "toggle"]
} }
} }
@@ -633,4 +633,20 @@ Singleton {
} }
Pipewire.preferredDefaultAudioSource = newSource; Pipewire.preferredDefaultAudioSource = newSource;
} }
onMutedChanged: {
if (root.muted) {
TempNotificationService.showWithIcon("volume-mute", "Muted");
} else {
TempNotificationService.showWithIcon(root.getOutputIcon(), Math.round(root.volume * 100) + "%");
}
}
onInputMutedChanged: {
if (root.inputMuted) {
TempNotificationService.showWithIcon("microphone-mute", "Input Muted");
} else {
TempNotificationService.showWithIcon("microphone", "Input Unmuted");
}
}
} }
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import qs.Services
import qs.Utils import qs.Utils
pragma Singleton pragma Singleton
@@ -161,6 +162,9 @@ Singleton {
Component.onDestruction: { Component.onDestruction: {
stopInhibition(); stopInhibition();
} }
onIsInhibitedChanged: {
TempNotificationService.showWithIcon("mug-filled", isInhibited ? "Inhibition active: " + reason : "Inhibition stopped");
}
// Process for maintaining the inhibition (subprocess fallback only) // Process for maintaining the inhibition (subprocess fallback only)
Process { Process {
@@ -153,4 +153,16 @@ Item {
target: "notes" target: "notes"
} }
IpcHandler {
function showMsg(message: string, duration: int) {
TempNotificationService.show(message, duration);
}
function showWithIcon(iconName: string, message: string, duration: int) {
TempNotificationService.showWithIcon(iconName, message, duration);
}
target: "tempNotification"
}
} }
@@ -193,7 +193,10 @@ Singleton {
} }
} }
onInternalPositionChanged: updateIndex() onInternalPositionChanged: updateIndex()
onLyricsOffsetChanged: updateIndex() onLyricsOffsetChanged: () => {
TempNotificationService.showWithIcon("hourglass-empty", root.lyricsOffset + "ms");
updateIndex()
}
Connections { Connections {
function onCurrentPlayerChanged() { function onCurrentPlayerChanged() {
@@ -280,6 +280,9 @@ Singleton {
currentPosition = 0; currentPosition = 0;
} }
onTrackTitleChanged: {
TempNotificationService.showWithIcon("music", trackArtist + " - " + trackTitle, 3000);
}
// Update progress bar every second while playing // Update progress bar every second while playing
Timer { Timer {
@@ -46,8 +46,10 @@ Singleton {
if (!sunsetProcess.running) { if (!sunsetProcess.running) {
temperature = 0; temperature = 0;
Logger.i("Sunset", "Stopped sunset process"); Logger.i("Sunset", "Stopped sunset process");
TempNotificationService.showWithIcon("sunset-2-filled", "Sunset disabled");
} else { } else {
Logger.i("Sunset", "Started sunset process"); Logger.i("Sunset", "Started sunset process");
TempNotificationService.showWithIcon("sunset-2-filled", "Sunset enabled");
} }
} }
@@ -0,0 +1,38 @@
pragma Singleton
import QtQuick
import Quickshell
Singleton {
id: root
readonly property int defaultDuration: 2000
property bool active: false
property string message: ""
property string iconName: ""
function show(message: string, duration: int) {
root._showInternal("", message, duration);
}
function showWithIcon(iconName: string, message: string, duration: int) {
root._showInternal(iconName, message, duration);
}
function _showInternal(iconName: string, message: string, duration: int) {
root.iconName = iconName;
root.message = message;
root.active = true;
resetTimer.interval = duration > 0 ? duration : root.defaultDuration;
resetTimer.restart();
}
Timer {
id: resetTimer
repeat: false
onTriggered: root.active = false
}
}