PluginSystem+Toast: added toast actiong to go straight to the plugin tab

This commit is contained in:
Lemmy
2026-01-01 09:58:03 -05:00
parent 7ca7c53be8
commit 081bed3034
5 changed files with 66 additions and 24 deletions
+3 -1
View File
@@ -2246,7 +2246,9 @@
"update": "Update",
"update-all": "Update All ({count})",
"update-all-success": "All plugins updated successfully",
"update-available": "{count} plugins update(s) available",
"update-available": "{count} plugin update available",
"update-available_plural": "{count} plugin updates available",
"open-plugins-tab": "Open plugins settings",
"update-error": "Failed to update plugin: {plugin}: {error}",
"update-incompatible": "Requires Noctalia v{version} or higher",
"update-success": "Updated {plugin} to v{version}",
+26 -9
View File
@@ -12,6 +12,8 @@ Item {
property string icon: ""
property string type: "notice"
property int duration: 3000
property string actionLabel: ""
property var actionCallback: null
readonly property real initialScale: 0.7
signal hidden
@@ -94,6 +96,14 @@ Item {
hideAnimation.stop();
}
// Click anywhere dismiss the toast (must be before content so action link can override)
MouseArea {
anchors.fill: background
acceptedButtons: Qt.LeftButton
onClicked: root.hide()
cursorShape: Qt.PointingHandCursor
}
RowLayout {
id: contentLayout
anchors.fill: background
@@ -152,18 +162,23 @@ Item {
wrapMode: Text.WordWrap
visible: text.length > 0
}
// Action button
NButton {
text: root.actionLabel
visible: root.actionLabel.length > 0 && root.actionCallback !== null
Layout.topMargin: Style.marginXS
onClicked: {
if (root.actionCallback) {
root.actionCallback();
root.hide();
}
}
}
}
}
// Click anywhere dismiss the toast
MouseArea {
anchors.fill: background
acceptedButtons: Qt.LeftButton
onClicked: root.hide()
cursorShape: Qt.PointingHandCursor
}
function show(msg, desc, msgIcon, msgType, msgDuration) {
function show(msg, desc, msgIcon, msgType, msgDuration, msgActionLabel, msgActionCallback) {
// Stop all timers first
hideTimer.stop();
hideAnimation.stop();
@@ -173,6 +188,8 @@ Item {
icon = msgIcon || "";
type = msgType || "notice";
duration = msgDuration || 3000;
actionLabel = msgActionLabel || "";
actionCallback = msgActionCallback || null;
visible = true;
opacity = 1;
+6 -4
View File
@@ -20,13 +20,15 @@ Item {
Connections {
target: ToastService
function onNotify(message, description, icon, type, duration) {
function onNotify(message, description, icon, type, duration, actionLabel, actionCallback) {
root.enqueueToast({
"message": message,
"description": description,
"icon": icon,
"type": type,
"duration": duration,
"actionLabel": actionLabel || "",
"actionCallback": actionCallback || null,
"timestamp": Date.now()
});
}
@@ -121,7 +123,7 @@ Item {
onStatusChanged: {
// When loader becomes ready, show the pending toast
if (status === Loader.Ready && pendingToast !== null) {
item.showToast(pendingToast.message, pendingToast.description, pendingToast.icon, pendingToast.type, pendingToast.duration);
item.showToast(pendingToast.message, pendingToast.description, pendingToast.icon, pendingToast.type, pendingToast.duration, pendingToast.actionLabel, pendingToast.actionCallback);
pendingToast = null;
}
}
@@ -215,8 +217,8 @@ Item {
}
}
function showToast(message, description, icon, type, duration) {
toastItem.show(message, description, icon, type, duration);
function showToast(message, description, icon, type, duration, actionLabel, actionCallback) {
toastItem.show(message, description, icon, type, duration, actionLabel, actionCallback);
}
function hideToast() {
+22 -3
View File
@@ -4,6 +4,7 @@ import QtQuick
import Quickshell
import Quickshell.Io
import qs.Commons
import qs.Modules.Panels.Settings
import qs.Services.Noctalia
import qs.Services.UI
@@ -1143,9 +1144,27 @@ Singleton {
if (updateCount > 0) {
Logger.i("PluginService", updateCount, "plugin update(s) available");
ToastService.showNotice(I18n.tr("settings.plugins.update-available", {
"count": updateCount
}), I18n.tr("common.check-settings"));
ToastService.showNotice(I18n.trp("settings.plugins.update-available", updateCount, "{count} plugin update available", "{count} plugin updates available", {
"count": updateCount
}), "", "plugin", 5000, I18n.tr("settings.plugins.open-plugins-tab"), function () {
// Open settings panel to Plugins tab on the screen where the cursor is
if (root.screenDetector) {
root.screenDetector.withCurrentScreen(function (screen) {
var panel = PanelService.getPanel("settingsPanel", screen);
if (panel) {
panel.requestedTab = SettingsPanel.Tab.Plugins;
panel.open();
}
});
} else {
// Fallback to primary screen if screen detector is not available
var panel = PanelService.getPanel("settingsPanel", Quickshell.screens[0]);
if (panel) {
panel.requestedTab = SettingsPanel.Tab.Plugins;
panel.open();
}
}
});
} else {
Logger.i("PluginService", "All plugins are up to date");
}
+9 -7
View File
@@ -7,18 +7,20 @@ Singleton {
id: root
// Simple signal-based notification system
signal notify(string message, string description, string icon, string type, int duration)
// actionLabel: optional label for clickable action link
// actionCallback: optional function to call when action is clicked
signal notify(string message, string description, string icon, string type, int duration, string actionLabel, var actionCallback)
// Convenience methods
function showNotice(message, description = "", icon = "", duration = 3000) {
notify(message, description, icon, "notice", duration);
function showNotice(message, description = "", icon = "", duration = 3000, actionLabel = "", actionCallback = null) {
notify(message, description, icon, "notice", duration, actionLabel, actionCallback);
}
function showWarning(message, description = "", duration = 4000) {
notify(message, description, "", "warning", duration);
function showWarning(message, description = "", duration = 4000, actionLabel = "", actionCallback = null) {
notify(message, description, "", "warning", duration, actionLabel, actionCallback);
}
function showError(message, description = "", duration = 6000) {
notify(message, description, "", "error", duration);
function showError(message, description = "", duration = 6000, actionLabel = "", actionCallback = null) {
notify(message, description, "", "error", duration, actionLabel, actionCallback);
}
}