notifs/toasts: reverted all changes to notifications to c0ea060f

This commit is contained in:
ATMDA 2025-11-12 20:57:38 -05:00
parent 7e6f327091
commit ffe14748a2
11 changed files with 61 additions and 609 deletions

View file

@ -8,10 +8,6 @@ import qs.modules.bar.popouts as BarPopouts
import qs.modules.utilities as Utilities import qs.modules.utilities as Utilities
import qs.modules.utilities.toasts as Toasts import qs.modules.utilities.toasts as Toasts
import qs.modules.sidebar as Sidebar import qs.modules.sidebar as Sidebar
import qs.components
import qs.components.controls
import qs.components.effects
import qs.services
import Quickshell import Quickshell
import QtQuick import QtQuick
@ -31,7 +27,6 @@ Item {
readonly property alias utilities: utilities readonly property alias utilities: utilities
readonly property alias toasts: toasts readonly property alias toasts: toasts
readonly property alias sidebar: sidebar readonly property alias sidebar: sidebar
readonly property alias clearAllButton: clearAllButton
anchors.fill: parent anchors.fill: parent
anchors.margins: Config.border.thickness anchors.margins: Config.border.thickness
@ -59,89 +54,6 @@ Item {
anchors.right: parent.right anchors.right: parent.right
} }
// Clear all notifications button - positioned to the left of the notification panel
Item {
id: clearAllButton
readonly property bool hasNotifications: Notifs.notClosed.length > 0
readonly property bool panelVisible: notifications.height > 0 || notifications.implicitHeight > 0
readonly property bool shouldShow: hasNotifications && panelVisible
anchors.top: notifications.top
anchors.right: notifications.left
anchors.rightMargin: Appearance.padding.normal
anchors.topMargin: Appearance.padding.large
width: button.implicitWidth
height: button.implicitHeight
enabled: shouldShow
IconButton {
id: button
icon: "clear_all"
radius: Appearance.rounding.normal
padding: Appearance.padding.normal
font.pointSize: Math.round(Appearance.font.size.large * 1.2)
onClicked: {
// Clear all notifications
for (const notif of Notifs.list.slice())
notif.close();
}
Elevation {
anchors.fill: parent
radius: parent.radius
z: -1
level: button.stateLayer.containsMouse ? 4 : 3
}
}
// Keep notification panel visible when hovering over the button
MouseArea {
anchors.fill: button
hoverEnabled: true
acceptedButtons: Qt.NoButton
onEntered: {
if (notifications.content && Notifs.notClosed.length > 0) {
notifications.content.show();
}
}
onExited: {
// Panel will be hidden by Interactions.qml if mouse is not over panel or button
}
}
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on scale {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
opacity: shouldShow ? 1 : 0
scale: shouldShow ? 1 : 0.5
}
Notifications.NotificationToasts {
id: notificationToasts
panels: root
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: Config.border.thickness
anchors.rightMargin: Config.border.thickness
}
Session.Wrapper { Session.Wrapper {
id: session id: session

View file

@ -22,7 +22,7 @@ ColumnLayout {
StyledText { StyledText {
Layout.fillWidth: true Layout.fillWidth: true
text: Notifs.notClosed.length > 0 ? qsTr("%1 notification%2").arg(Notifs.notClosed.length).arg(Notifs.notClosed.length === 1 ? "" : "s") : qsTr("Notifications") text: Notifs.list.length > 0 ? qsTr("%1 notification%2").arg(Notifs.list.length).arg(Notifs.list.length === 1 ? "" : "s") : qsTr("Notifications")
color: Colours.palette.m3outline color: Colours.palette.m3outline
font.family: Appearance.font.family.mono font.family: Appearance.font.family.mono
font.weight: 500 font.weight: 500
@ -42,7 +42,7 @@ ColumnLayout {
anchors.centerIn: parent anchors.centerIn: parent
asynchronous: true asynchronous: true
active: opacity > 0 active: opacity > 0
opacity: Notifs.notClosed.length > 0 ? 0 : 1 opacity: Notifs.list.length > 0 ? 0 : 1
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: Appearance.spacing.large spacing: Appearance.spacing.large

View file

@ -16,7 +16,7 @@ StyledRect {
required property string modelData required property string modelData
readonly property list<var> notifs: Notifs.notClosed.filter(notif => notif.appName === modelData) readonly property list<var> notifs: Notifs.list.filter(notif => notif.appName === modelData)
readonly property string image: notifs.find(n => n.image.length > 0)?.image ?? "" readonly property string image: notifs.find(n => n.image.length > 0)?.image ?? ""
readonly property string appIcon: notifs.find(n => n.appIcon.length > 0)?.appIcon ?? "" readonly property string appIcon: notifs.find(n => n.appIcon.length > 0)?.appIcon ?? ""
readonly property string urgency: notifs.some(n => n.urgency === NotificationUrgency.Critical) ? "critical" : notifs.some(n => n.urgency === NotificationUrgency.Normal) ? "normal" : "low" readonly property string urgency: notifs.some(n => n.urgency === NotificationUrgency.Critical) ? "critical" : notifs.some(n => n.urgency === NotificationUrgency.Normal) ? "normal" : "low"

View file

@ -1,57 +0,0 @@
import qs.components
import qs.components.effects
import qs.services
import qs.config
import qs.utils
import Quickshell
import Quickshell.Services.Notifications
import QtQuick
StyledRect {
id: root
required property Notifs.Notif modelData
required property bool hasImage
required property bool hasAppIcon
radius: Appearance.rounding.full
color: modelData.getBadgeBackgroundColor()
implicitWidth: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
implicitHeight: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
Loader {
id: icon
active: root.hasAppIcon
asynchronous: false
visible: active
anchors.centerIn: parent
width: Math.round(parent.width * 0.6)
height: Math.round(parent.width * 0.6)
sourceComponent: ColouredIcon {
anchors.fill: parent
source: Quickshell.iconPath(root.modelData.appIcon)
colour: root.modelData.getIconColor()
layer.enabled: root.modelData.appIcon.endsWith("symbolic")
}
}
Loader {
active: !root.hasAppIcon
asynchronous: false
visible: active
anchors.centerIn: parent
anchors.horizontalCenterOffset: -Appearance.font.size.large * 0.02
anchors.verticalCenterOffset: Appearance.font.size.large * 0.02
sourceComponent: MaterialIcon {
text: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency)
color: root.modelData.getIconColor()
font.pointSize: Appearance.font.size.large
}
}
}

View file

@ -13,8 +13,6 @@ Item {
required property Item panels required property Item panels
readonly property int padding: Appearance.padding.large readonly property int padding: Appearance.padding.large
property bool shouldShow: false
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
@ -22,16 +20,13 @@ Item {
implicitWidth: Config.notifs.sizes.width + padding * 2 implicitWidth: Config.notifs.sizes.width + padding * 2
implicitHeight: { implicitHeight: {
const count = list.count; const count = list.count;
if (count === 0 || !shouldShow) if (count === 0)
return 0; return 0;
let height = (count - 1) * Appearance.spacing.smaller; let height = (count - 1) * Appearance.spacing.smaller;
for (let i = 0; i < count; i++) for (let i = 0; i < count; i++)
height += list.itemAtIndex(i)?.nonAnimHeight ?? 0; height += list.itemAtIndex(i)?.nonAnimHeight ?? 0;
const screenHeight = QsWindow.window?.screen?.height ?? 0;
const maxHeight = Math.floor(screenHeight * 0.45);
if (visibilities && panels) { if (visibilities && panels) {
if (visibilities.osd) { if (visibilities.osd) {
const h = panels.osd.y - Config.border.rounding * 2 - padding * 2; const h = panels.osd.y - Config.border.rounding * 2 - padding * 2;
@ -46,8 +41,7 @@ Item {
} }
} }
const availableHeight = Math.min(maxHeight, screenHeight - Config.border.thickness * 2); return Math.min((QsWindow.window?.screen?.height ?? 0) - Config.border.thickness * 2, height + padding * 2);
return Math.min(availableHeight, height + padding * 2);
} }
ClippingWrapperRectangle { ClippingWrapperRectangle {
@ -61,7 +55,7 @@ Item {
id: list id: list
model: ScriptModel { model: ScriptModel {
values: [...Notifs.notClosed] values: Notifs.popups.filter(n => !n.closed)
} }
anchors.fill: parent anchors.fill: parent
@ -198,52 +192,6 @@ Item {
} }
} }
Timer {
id: hideTimer
interval: 5000
onTriggered: {
if (list.count > 0)
root.shouldShow = false;
}
}
function show(): void {
if (list.count > 0) {
shouldShow = true;
hideTimer.restart();
}
}
Connections {
target: list
function onCountChanged(): void {
if (list.count === 0) {
root.shouldShow = false;
hideTimer.stop();
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
onEntered: {
if (list.count > 0) {
root.shouldShow = true;
hideTimer.restart();
}
}
onExited: {
if (list.count > 0) {
root.shouldShow = false;
hideTimer.stop();
}
}
}
Behavior on implicitHeight { Behavior on implicitHeight {
Anim {} Anim {}
} }

View file

@ -17,31 +17,22 @@ StyledRect {
required property Notifs.Notif modelData required property Notifs.Notif modelData
readonly property bool hasImage: modelData.image.length > 0 readonly property bool hasImage: modelData.image.length > 0
readonly property bool hasAppIcon: modelData.appIcon.length > 0 readonly property bool hasAppIcon: modelData.appIcon.length > 0
readonly property int nonAnimHeight: { readonly property int nonAnimHeight: summary.implicitHeight + (root.expanded ? appName.height + body.height + actions.height + actions.anchors.topMargin : bodyPreview.height) + inner.anchors.margins * 2
const baseHeight = summary.implicitHeight + inner.anchors.margins * 2;
return root.expanded
? baseHeight + appName.height + body.height + actions.height + actions.anchors.topMargin
: baseHeight + bodyPreview.height;
}
property bool expanded property bool expanded
property bool disableSlideIn: false
color: modelData.getBackgroundColor() color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3secondaryContainer : Colours.tPalette.m3surfaceContainer
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
implicitWidth: Config.notifs.sizes.width implicitWidth: Config.notifs.sizes.width
implicitHeight: inner.implicitHeight implicitHeight: inner.implicitHeight
x: disableSlideIn ? 0 : Config.notifs.sizes.width x: Config.notifs.sizes.width
Component.onCompleted: { Component.onCompleted: {
if (!root.disableSlideIn) {
x = 0; x = 0;
}
modelData.lock(this); modelData.lock(this);
} }
Component.onDestruction: modelData.unlock(this) Component.onDestruction: modelData.unlock(this)
Behavior on x { Behavior on x {
enabled: !disableSlideIn
Anim { Anim {
easing.bezierCurve: Appearance.anim.curves.emphasizedDecel easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
} }
@ -143,18 +134,53 @@ StyledRect {
Loader { Loader {
id: appIcon id: appIcon
active: !root.hasImage || root.hasAppIcon active: root.hasAppIcon || !root.hasImage
asynchronous: false asynchronous: true
anchors.horizontalCenter: root.hasImage ? undefined : image.horizontalCenter anchors.horizontalCenter: root.hasImage ? undefined : image.horizontalCenter
anchors.verticalCenter: root.hasImage ? undefined : image.verticalCenter anchors.verticalCenter: root.hasImage ? undefined : image.verticalCenter
anchors.right: root.hasImage ? image.right : undefined anchors.right: root.hasImage ? image.right : undefined
anchors.bottom: root.hasImage ? image.bottom : undefined anchors.bottom: root.hasImage ? image.bottom : undefined
sourceComponent: AppIconBadge { sourceComponent: StyledRect {
modelData: root.modelData radius: Appearance.rounding.full
hasImage: root.hasImage color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) : Colours.palette.m3secondaryContainer
hasAppIcon: root.hasAppIcon implicitWidth: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
implicitHeight: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
Loader {
id: icon
active: root.hasAppIcon
asynchronous: true
anchors.centerIn: parent
width: Math.round(parent.width * 0.6)
height: Math.round(parent.width * 0.6)
sourceComponent: ColouredIcon {
anchors.fill: parent
source: Quickshell.iconPath(root.modelData.appIcon)
colour: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
layer.enabled: root.modelData.appIcon.endsWith("symbolic")
}
}
Loader {
active: !root.hasAppIcon
asynchronous: true
anchors.centerIn: parent
anchors.horizontalCenterOffset: -Appearance.font.size.large * 0.02
anchors.verticalCenterOffset: Appearance.font.size.large * 0.02
sourceComponent: MaterialIcon {
text: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency)
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
font.pointSize: Appearance.font.size.large
}
}
} }
} }
@ -296,7 +322,7 @@ StyledRect {
StateLayer { StateLayer {
radius: Appearance.rounding.full radius: Appearance.rounding.full
color: root.modelData.getStateLayerColor() color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
function onClicked() { function onClicked() {
root.expanded = !root.expanded; root.expanded = !root.expanded;
@ -417,7 +443,7 @@ StyledRect {
required property var modelData required property var modelData
radius: Appearance.rounding.full radius: Appearance.rounding.full
color: root.modelData.getActionBackgroundColor() color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3secondary : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
Layout.preferredWidth: actionText.width + Appearance.padding.normal * 2 Layout.preferredWidth: actionText.width + Appearance.padding.normal * 2
Layout.preferredHeight: actionText.height + Appearance.padding.small * 2 Layout.preferredHeight: actionText.height + Appearance.padding.small * 2
@ -426,7 +452,7 @@ StyledRect {
StateLayer { StateLayer {
radius: Appearance.rounding.full radius: Appearance.rounding.full
color: root.modelData.getStateLayerColor() color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onSecondary : Colours.palette.m3onSurface
function onClicked(): void { function onClicked(): void {
action.modelData.invoke(); action.modelData.invoke();
@ -438,7 +464,7 @@ StyledRect {
anchors.centerIn: parent anchors.centerIn: parent
text: actionTextMetrics.elidedText text: actionTextMetrics.elidedText
color: root.modelData.getActionTextColor() color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onSecondary : Colours.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.small font.pointSize: Appearance.font.size.small
} }

View file

@ -1,120 +0,0 @@
import qs.components
import qs.components.effects
import qs.services
import qs.config
import qs.utils
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.Notifications
import QtQuick
import QtQuick.Layouts
StyledRect {
id: root
required property Notifs.Notif modelData
readonly property bool hasImage: modelData.image.length > 0
readonly property bool hasAppIcon: modelData.appIcon.length > 0
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: layout.implicitHeight + Appearance.padding.smaller * 2
radius: Appearance.rounding.normal
color: Colours.palette.m3surface
border.width: 1
border.color: Colours.palette.m3outlineVariant
Elevation {
anchors.fill: parent
radius: parent.radius
opacity: parent.opacity
z: -1
level: 3
}
RowLayout {
id: layout
anchors.fill: parent
anchors.margins: Appearance.padding.smaller
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.normal
spacing: Appearance.spacing.normal
Item {
Layout.preferredWidth: Config.notifs.sizes.image
Layout.preferredHeight: Config.notifs.sizes.image
Loader {
id: imageLoader
active: root.hasImage
asynchronous: true
anchors.fill: parent
sourceComponent: ClippingRectangle {
radius: Appearance.rounding.full
implicitWidth: Config.notifs.sizes.image
implicitHeight: Config.notifs.sizes.image
Image {
anchors.fill: parent
source: Qt.resolvedUrl(root.modelData.image)
fillMode: Image.PreserveAspectCrop
cache: false
asynchronous: true
}
}
}
Loader {
id: appIconLoader
active: root.hasAppIcon || !root.hasImage
asynchronous: true
anchors.horizontalCenter: root.hasImage ? undefined : parent.horizontalCenter
anchors.verticalCenter: root.hasImage ? undefined : parent.verticalCenter
anchors.right: root.hasImage ? parent.right : undefined
anchors.bottom: root.hasImage ? parent.bottom : undefined
sourceComponent: AppIconBadge {
modelData: root.modelData
hasImage: root.hasImage
hasAppIcon: root.hasAppIcon
}
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
StyledText {
id: title
Layout.fillWidth: true
text: root.modelData.summary
color: Colours.palette.m3onSurface
font.pointSize: Appearance.font.size.normal
elide: Text.ElideRight
}
StyledText {
Layout.fillWidth: true
textFormat: Text.StyledText
text: root.modelData.body
color: Colours.palette.m3onSurface
opacity: 0.8
elide: Text.ElideRight
}
}
}
Behavior on border.color {
CAnim {}
}
}

View file

@ -1,186 +0,0 @@
pragma ComponentBehavior: Bound
import qs.components
import qs.config
import qs.services
import Quickshell
import Quickshell.Widgets
import QtQuick
Item {
id: root
required property Item panels
readonly property int spacing: Appearance.spacing.small
readonly property int maxToasts: 5
readonly property bool listVisible: panels.notifications.content.shouldShow
property bool flag
property var activeToasts: new Set()
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: Appearance.padding.normal
implicitWidth: Config.notifs.sizes.width
implicitHeight: {
if (listVisible)
return 0;
let height = -spacing;
for (let i = 0; i < repeater.count; i++) {
const item = repeater.itemAt(i) as ToastWrapper;
if (item && !item.modelData.closed && !item.previewHidden)
height += item.implicitHeight + spacing;
}
return height;
}
opacity: listVisible ? 0 : 1
visible: opacity > 0
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
}
}
Repeater {
id: repeater
model: ScriptModel {
values: {
const toasts = [];
let visibleCount = 0;
for (const notif of Notifs.list) {
if (notif.showAsToast) {
root.activeToasts.add(notif);
}
if (notif.closed) {
root.activeToasts.delete(notif);
}
}
for (const notif of Notifs.list) {
if (root.activeToasts.has(notif)) {
toasts.push(notif);
if (notif.showAsToast && !notif.closed) {
visibleCount++;
if (visibleCount > root.maxToasts)
break;
}
}
}
return toasts;
}
onValuesChanged: root.flagChanged()
}
ToastWrapper {}
}
component ToastWrapper: MouseArea {
id: toast
required property int index
required property Notifs.Notif modelData
readonly property bool previewHidden: {
let extraHidden = 0;
for (let i = 0; i < index; i++) {
const item = repeater.itemAt(i);
if (item && item.modelData.closed)
extraHidden++;
}
return index >= root.maxToasts + extraHidden;
}
opacity: modelData.closed || previewHidden || !modelData.showAsToast ? 0 : 1
scale: modelData.closed || previewHidden || !modelData.showAsToast ? 0.7 : 1
anchors.topMargin: {
root.flag;
let margin = 0;
for (let i = 0; i < index; i++) {
const item = repeater.itemAt(i) as ToastWrapper;
if (item && !item.modelData.closed && !item.previewHidden)
margin += item.implicitHeight + root.spacing;
}
return margin;
}
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
implicitHeight: toastInner.implicitHeight
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
onClicked: {
modelData.showAsToast = false;
modelData.close();
}
Component.onCompleted: modelData.lock(this)
onPreviewHiddenChanged: {
if (initAnim.running && previewHidden)
initAnim.stop();
}
Anim {
id: initAnim
Component.onCompleted: running = !toast.previewHidden
target: toast
properties: "opacity,scale"
from: 0
to: 1
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
ParallelAnimation {
running: toast.modelData.closed || (!toast.modelData.showAsToast && !toast.modelData.closed)
onStarted: toast.anchors.topMargin = toast.anchors.topMargin
onFinished: {
if (toast.modelData.closed)
toast.modelData.unlock(toast);
}
Anim {
target: toast
property: "opacity"
to: 0
}
Anim {
target: toast
property: "scale"
to: 0.7
}
}
NotificationToast {
id: toastInner
modelData: toast.modelData
}
Behavior on opacity {
Anim {}
}
Behavior on scale {
Anim {}
}
Behavior on anchors.topMargin {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
}
}

View file

@ -8,8 +8,6 @@ Item {
required property var visibilities required property var visibilities
required property Item panels required property Item panels
readonly property alias content: content
visible: height > 0 visible: height > 0
implicitWidth: Math.max(panels.sidebar.width, content.implicitWidth) implicitWidth: Math.max(panels.sidebar.width, content.implicitWidth)
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight

View file

@ -28,13 +28,14 @@ StyledRect {
border.width: 1 border.width: 1
border.color: { border.color: {
let colour = Colours.palette.m3outlineVariant;
if (root.modelData.type === Toast.Success) if (root.modelData.type === Toast.Success)
return Colours.palette.m3success; colour = Colours.palette.m3success;
if (root.modelData.type === Toast.Warning) if (root.modelData.type === Toast.Warning)
return Colours.palette.m3secondaryContainer; colour = Colours.palette.m3secondaryContainer;
if (root.modelData.type === Toast.Error) if (root.modelData.type === Toast.Error)
return Colours.palette.m3error; colour = Colours.palette.m3error;
return Colours.palette.m3outlineVariant; return Qt.alpha(colour, 0.3);
} }
Elevation { Elevation {

View file

@ -77,10 +77,8 @@ Singleton {
onNotification: notif => { onNotification: notif => {
notif.tracked = true; notif.tracked = true;
const shouldShowAsToast = !props.dnd && ![...Visibilities.screens.values()].some(v => v.sidebar);
const comp = notifComp.createObject(root, { const comp = notifComp.createObject(root, {
popup: shouldShowAsToast, popup: !props.dnd && ![...Visibilities.screens.values()].some(v => v.sidebar),
showAsToast: shouldShowAsToast,
notification: notif notification: notif
}); });
root.list = [comp, ...root.list]; root.list = [comp, ...root.list];
@ -145,7 +143,6 @@ Singleton {
property bool popup property bool popup
property bool closed property bool closed
property bool showAsToast: false
property var locks: new Set() property var locks: new Set()
property date time: new Date() property date time: new Date()
@ -179,74 +176,7 @@ Singleton {
property bool hasActionIcons property bool hasActionIcons
property list<var> actions property list<var> actions
readonly property bool isCritical: urgency === NotificationUrgency.Critical
readonly property bool isLow: urgency === NotificationUrgency.Low
function getBackgroundColor(): color {
if (isCritical) return Colours.palette.m3secondaryContainer;
return Colours.tPalette.m3surfaceContainer;
}
function getBadgeBackgroundColor(): color {
if (isCritical) return Colours.palette.m3error;
if (isLow) return Colours.layer(Colours.palette.m3surfaceContainerHighest, 2);
return Colours.palette.m3secondaryContainer;
}
function getIconColor(): color {
if (isCritical) return Colours.palette.m3onError;
if (isLow) return Colours.palette.m3onSurface;
return Colours.palette.m3onSecondaryContainer;
}
function getStateLayerColor(): color {
if (isCritical) return Colours.palette.m3onSecondaryContainer;
return Colours.palette.m3onSurface;
}
function getActionBackgroundColor(): color {
if (isCritical) return Colours.palette.m3secondary;
return Colours.layer(Colours.palette.m3surfaceContainerHigh, 2);
}
function getActionTextColor(): color {
if (isCritical) return Colours.palette.m3onSecondary;
return Colours.palette.m3onSurfaceVariant;
}
readonly property Timer timer: Timer { readonly property Timer timer: Timer {
id: toastTimer
running: notif.showAsToast
interval: {
let timeout = notif.expireTimeout;
if (timeout <= 0) {
switch (notif.urgency) {
case NotificationUrgency.Critical:
timeout = 10000;
break;
case NotificationUrgency.Normal:
timeout = 5000;
break;
case NotificationUrgency.Low:
timeout = 5000;
break;
default:
timeout = 5000;
}
}
return timeout;
}
onTriggered: {
if (Config.notifs.expire)
notif.popup = false;
if (notif.showAsToast) {
notif.showAsToast = false;
}
}
}
readonly property Timer popupTimer: Timer {
running: true running: true
interval: notif.expireTimeout > 0 ? notif.expireTimeout : Config.notifs.defaultExpireTimeout interval: notif.expireTimeout > 0 ? notif.expireTimeout : Config.notifs.defaultExpireTimeout
onTriggered: { onTriggered: {