mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
214 lines
6.0 KiB
QML
214 lines
6.0 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import qs.Common
|
|
import qs.Common.settings
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
readonly property int levelInfo: 0
|
|
readonly property int levelWarn: 1
|
|
readonly property int levelError: 2
|
|
property string currentMessage: ""
|
|
property int currentLevel: levelInfo
|
|
property bool toastVisible: false
|
|
property var toastQueue: []
|
|
property string currentDetails: ""
|
|
property string currentCommand: ""
|
|
property bool hasDetails: false
|
|
property string wallpaperErrorStatus: ""
|
|
property int maxQueueSize: 3
|
|
property var lastErrorTime: ({})
|
|
property int errorThrottleMs: 1000
|
|
property string currentCategory: ""
|
|
readonly property var stickyCategories: ["greeter-autologin-sync"]
|
|
|
|
function isStickyCategory(category) {
|
|
return category && stickyCategories.indexOf(category) >= 0;
|
|
}
|
|
|
|
function showToast(message, level = levelInfo, details = "", command = "", category = "") {
|
|
const now = Date.now();
|
|
const messageKey = message + level;
|
|
|
|
if (level === levelError) {
|
|
const lastTime = lastErrorTime[messageKey] || 0;
|
|
if (now - lastTime < errorThrottleMs) {
|
|
return;
|
|
}
|
|
lastErrorTime[messageKey] = now;
|
|
}
|
|
|
|
if (category && level === levelError) {
|
|
if (currentCategory === category && toastVisible && currentLevel === levelError) {
|
|
currentMessage = message;
|
|
currentDetails = details || "";
|
|
currentCommand = command || "";
|
|
hasDetails = currentDetails.length > 0 || currentCommand.length > 0;
|
|
resetToastState();
|
|
if (hasDetails) {
|
|
toastTimer.interval = 8000;
|
|
} else {
|
|
toastTimer.interval = 5000;
|
|
}
|
|
toastTimer.restart();
|
|
return;
|
|
}
|
|
|
|
toastQueue = toastQueue.filter(t => t.category !== category);
|
|
}
|
|
|
|
const isDuplicate = toastQueue.some(toast => toast.message === message && toast.level === level);
|
|
if (isDuplicate) {
|
|
return;
|
|
}
|
|
|
|
if (toastQueue.length >= maxQueueSize) {
|
|
if (level === levelError) {
|
|
toastQueue = toastQueue.filter(t => t.level !== levelError).slice(0, maxQueueSize - 1);
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
toastQueue.push({
|
|
"message": message,
|
|
"level": level,
|
|
"details": details,
|
|
"command": command,
|
|
"category": category
|
|
});
|
|
if (!toastVisible) {
|
|
processQueue();
|
|
}
|
|
}
|
|
|
|
function showInfo(message, details = "", command = "", category = "") {
|
|
showToast(message, levelInfo, details, command, category);
|
|
}
|
|
|
|
function showWarning(message, details = "", command = "", category = "") {
|
|
showToast(message, levelWarn, details, command, category);
|
|
}
|
|
|
|
function showError(message, details = "", command = "", category = "") {
|
|
showToast(message, levelError, details, command, category);
|
|
}
|
|
|
|
function dismissCategory(category) {
|
|
if (!category) {
|
|
return;
|
|
}
|
|
|
|
if (currentCategory === category && toastVisible) {
|
|
hideToast();
|
|
return;
|
|
}
|
|
|
|
toastQueue = toastQueue.filter(t => t.category !== category);
|
|
}
|
|
|
|
function hideToast() {
|
|
toastVisible = false;
|
|
currentMessage = "";
|
|
currentDetails = "";
|
|
currentCommand = "";
|
|
currentCategory = "";
|
|
hasDetails = false;
|
|
currentLevel = levelInfo;
|
|
toastTimer.stop();
|
|
resetToastState();
|
|
if (toastQueue.length > 0) {
|
|
processQueue();
|
|
}
|
|
}
|
|
|
|
function processQueue() {
|
|
if (toastQueue.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const toast = toastQueue.shift();
|
|
currentMessage = toast.message;
|
|
currentLevel = toast.level;
|
|
currentDetails = toast.details || "";
|
|
currentCommand = toast.command || "";
|
|
currentCategory = toast.category || "";
|
|
hasDetails = currentDetails.length > 0 || currentCommand.length > 0;
|
|
toastVisible = true;
|
|
resetToastState();
|
|
|
|
if (isStickyCategory(toast.category)) {
|
|
toastTimer.stop();
|
|
} else if (toast.level === levelError && hasDetails) {
|
|
toastTimer.interval = 8000;
|
|
toastTimer.start();
|
|
} else {
|
|
toastTimer.interval = toast.level === levelError ? 5000 : toast.level === levelWarn ? 3000 : 1500;
|
|
toastTimer.start();
|
|
}
|
|
}
|
|
|
|
signal resetToastState
|
|
|
|
function stopTimer() {
|
|
toastTimer.stop();
|
|
}
|
|
|
|
function restartTimer() {
|
|
if (isStickyCategory(currentCategory)) {
|
|
return;
|
|
}
|
|
if (hasDetails && currentLevel === levelError) {
|
|
toastTimer.interval = 8000;
|
|
toastTimer.restart();
|
|
}
|
|
}
|
|
|
|
function clearWallpaperError() {
|
|
wallpaperErrorStatus = "";
|
|
}
|
|
|
|
Timer {
|
|
id: toastTimer
|
|
|
|
interval: 5000
|
|
running: false
|
|
repeat: false
|
|
onTriggered: hideToast()
|
|
}
|
|
|
|
Connections {
|
|
target: SessionData
|
|
|
|
function onLoadErrorOccurred(file, message) {
|
|
root.showError(I18n.tr("Failed to parse %1").arg(file), message);
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: Processes
|
|
|
|
function onToastRequested(severity, title, body, command, category) {
|
|
switch (severity) {
|
|
case root.levelWarn:
|
|
root.showWarning(title, body, command, category);
|
|
break;
|
|
case root.levelError:
|
|
root.showError(title, body, command, category);
|
|
break;
|
|
default:
|
|
root.showInfo(title, body, command, category);
|
|
break;
|
|
}
|
|
}
|
|
|
|
function onToastCategoryDismissed(category) {
|
|
root.dismissCategory(category);
|
|
}
|
|
}
|
|
}
|