Add ToastService, NToast etc

This commit is contained in:
Ly-sec 2025-08-19 14:14:00 +02:00
parent 1993e28c18
commit 1d860da42e
18 changed files with 534 additions and 31 deletions

214
Services/ToastService.qml Normal file
View file

@ -0,0 +1,214 @@
pragma Singleton
import QtQuick
import Quickshell.Io
import qs.Commons
QtObject {
id: root
// Queue of pending toast messages
property var messageQueue: []
property bool isShowingToast: false
// Reference to the current toast instance (set by ToastManager)
property var currentToast: null
// Methods to show different types of messages
function showNotice(message, persistent = false, duration = 3000) {
showToast(message, "notice", persistent, duration)
}
function showWarning(message, persistent = false, duration = 4000) {
showToast(message, "warning", persistent, duration)
}
// Utility function to check if a command exists and show appropriate toast
function checkCommandAndToast(command, successMessage, failMessage, onSuccess = null) {
var checkProcess = Qt.createQmlObject(`
import QtQuick
import Quickshell.Io
Process {
id: checkProc
command: ["which", "${command}"]
running: true
property var onSuccessCallback: null
property bool hasFinished: false
onExited: {
if (!hasFinished) {
hasFinished = true
if (exitCode === 0) {
ToastService.showNotice("${successMessage}")
if (onSuccessCallback) onSuccessCallback()
} else {
ToastService.showWarning("${failMessage}")
}
checkProc.destroy()
}
}
// Fallback collectors to prevent issues
stdout: StdioCollector {}
stderr: StdioCollector {}
}
`, root)
checkProcess.onSuccessCallback = onSuccess
}
// Simple function to show a random toast (useful for testing or fun messages)
function showRandomToast() {
var messages = [
{ type: "notice", text: "Everything is working smoothly!" },
{ type: "notice", text: "Noctalia is looking great today!" },
{ type: "notice", text: "Your desktop setup is amazing!" },
{ type: "warning", text: "Don't forget to take a break!" },
{ type: "notice", text: "Configuration saved successfully!" },
{ type: "warning", text: "Remember to backup your settings!" }
]
var randomMessage = messages[Math.floor(Math.random() * messages.length)]
showToast(randomMessage.text, randomMessage.type)
}
// Convenience function for quick notifications
function quickNotice(message) {
showNotice(message, false, 2000) // Short duration
}
function quickWarning(message) {
showWarning(message, false, 3000) // Medium duration
}
// Generic command runner with toast feedback
function runCommandWithToast(command, args, successMessage, failMessage, onSuccess = null) {
var fullCommand = [command].concat(args || [])
var runProcess = Qt.createQmlObject(`
import QtQuick
import Quickshell.Io
Process {
id: runProc
command: ${JSON.stringify(fullCommand)}
running: true
property var onSuccessCallback: null
property bool hasFinished: false
onExited: {
if (!hasFinished) {
hasFinished = true
if (exitCode === 0) {
ToastService.showNotice("${successMessage}")
if (onSuccessCallback) onSuccessCallback()
} else {
ToastService.showWarning("${failMessage}")
}
runProc.destroy()
}
}
stdout: StdioCollector {}
stderr: StdioCollector {}
}
`, root)
runProcess.onSuccessCallback = onSuccess
}
// Check if a file/directory exists
function checkPathAndToast(path, successMessage, failMessage, onSuccess = null) {
runCommandWithToast("test", ["-e", path], successMessage, failMessage, onSuccess)
}
// Show toast after a delay (useful for delayed feedback)
function delayedToast(message, type = "notice", delayMs = 1000) {
var timer = Qt.createQmlObject(`
import QtQuick
Timer {
interval: ${delayMs}
repeat: false
running: true
onTriggered: {
ToastService.showToast("${message}", "${type}")
destroy()
}
}
`, root)
}
// Generic method to show a toast
function showToast(message, type = "notice", persistent = false, duration = 3000) {
var toastData = {
message: message,
type: type,
persistent: persistent,
duration: duration,
timestamp: Date.now()
}
// Add to queue
messageQueue.push(toastData)
// Process queue if not currently showing a toast
if (!isShowingToast) {
processQueue()
}
}
// Process the message queue
function processQueue() {
if (messageQueue.length === 0 || !currentToast) {
isShowingToast = false
return
}
if (isShowingToast) {
// Wait for current toast to finish
return
}
var toastData = messageQueue.shift()
isShowingToast = true
// Configure and show toast
currentToast.message = toastData.message
currentToast.type = toastData.type
currentToast.persistent = toastData.persistent
currentToast.duration = toastData.duration
currentToast.show()
}
// Called when a toast is dismissed
function onToastDismissed() {
isShowingToast = false
// Small delay before showing next toast
Qt.callLater(function() {
processQueue()
})
}
// Clear all pending messages
function clearQueue() {
messageQueue = []
}
// Hide current toast
function hideCurrentToast() {
if (currentToast && isShowingToast) {
currentToast.hide()
}
}
Component.onCompleted: {
}
}