notifs/toasts: reverted all changes to notifications to c0ea060f
This commit is contained in:
parent
7e6f327091
commit
ffe14748a2
11 changed files with 61 additions and 609 deletions
|
|
@ -8,10 +8,6 @@ import qs.modules.bar.popouts as BarPopouts
|
|||
import qs.modules.utilities as Utilities
|
||||
import qs.modules.utilities.toasts as Toasts
|
||||
import qs.modules.sidebar as Sidebar
|
||||
import qs.components
|
||||
import qs.components.controls
|
||||
import qs.components.effects
|
||||
import qs.services
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
|
||||
|
|
@ -31,7 +27,6 @@ Item {
|
|||
readonly property alias utilities: utilities
|
||||
readonly property alias toasts: toasts
|
||||
readonly property alias sidebar: sidebar
|
||||
readonly property alias clearAllButton: clearAllButton
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Config.border.thickness
|
||||
|
|
@ -59,89 +54,6 @@ Item {
|
|||
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 {
|
||||
id: session
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ ColumnLayout {
|
|||
|
||||
StyledText {
|
||||
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
|
||||
font.family: Appearance.font.family.mono
|
||||
font.weight: 500
|
||||
|
|
@ -42,7 +42,7 @@ ColumnLayout {
|
|||
anchors.centerIn: parent
|
||||
asynchronous: true
|
||||
active: opacity > 0
|
||||
opacity: Notifs.notClosed.length > 0 ? 0 : 1
|
||||
opacity: Notifs.list.length > 0 ? 0 : 1
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
spacing: Appearance.spacing.large
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ StyledRect {
|
|||
|
||||
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 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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -13,8 +13,6 @@ Item {
|
|||
required property Item panels
|
||||
readonly property int padding: Appearance.padding.large
|
||||
|
||||
property bool shouldShow: false
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
|
|
@ -22,16 +20,13 @@ Item {
|
|||
implicitWidth: Config.notifs.sizes.width + padding * 2
|
||||
implicitHeight: {
|
||||
const count = list.count;
|
||||
if (count === 0 || !shouldShow)
|
||||
if (count === 0)
|
||||
return 0;
|
||||
|
||||
let height = (count - 1) * Appearance.spacing.smaller;
|
||||
for (let i = 0; i < count; i++)
|
||||
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.osd) {
|
||||
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(availableHeight, height + padding * 2);
|
||||
return Math.min((QsWindow.window?.screen?.height ?? 0) - Config.border.thickness * 2, height + padding * 2);
|
||||
}
|
||||
|
||||
ClippingWrapperRectangle {
|
||||
|
|
@ -61,7 +55,7 @@ Item {
|
|||
id: list
|
||||
|
||||
model: ScriptModel {
|
||||
values: [...Notifs.notClosed]
|
||||
values: Notifs.popups.filter(n => !n.closed)
|
||||
}
|
||||
|
||||
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 {
|
||||
Anim {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,31 +17,22 @@ StyledRect {
|
|||
required property Notifs.Notif modelData
|
||||
readonly property bool hasImage: modelData.image.length > 0
|
||||
readonly property bool hasAppIcon: modelData.appIcon.length > 0
|
||||
readonly property int nonAnimHeight: {
|
||||
const baseHeight = summary.implicitHeight + inner.anchors.margins * 2;
|
||||
return root.expanded
|
||||
? baseHeight + appName.height + body.height + actions.height + actions.anchors.topMargin
|
||||
: baseHeight + bodyPreview.height;
|
||||
}
|
||||
readonly property int nonAnimHeight: summary.implicitHeight + (root.expanded ? appName.height + body.height + actions.height + actions.anchors.topMargin : bodyPreview.height) + inner.anchors.margins * 2
|
||||
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
|
||||
implicitWidth: Config.notifs.sizes.width
|
||||
implicitHeight: inner.implicitHeight
|
||||
|
||||
x: disableSlideIn ? 0 : Config.notifs.sizes.width
|
||||
x: Config.notifs.sizes.width
|
||||
Component.onCompleted: {
|
||||
if (!root.disableSlideIn) {
|
||||
x = 0;
|
||||
}
|
||||
x = 0;
|
||||
modelData.lock(this);
|
||||
}
|
||||
Component.onDestruction: modelData.unlock(this)
|
||||
|
||||
Behavior on x {
|
||||
enabled: !disableSlideIn
|
||||
Anim {
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
|
||||
}
|
||||
|
|
@ -143,18 +134,53 @@ StyledRect {
|
|||
Loader {
|
||||
id: appIcon
|
||||
|
||||
active: !root.hasImage || root.hasAppIcon
|
||||
asynchronous: false
|
||||
active: root.hasAppIcon || !root.hasImage
|
||||
asynchronous: true
|
||||
|
||||
anchors.horizontalCenter: root.hasImage ? undefined : image.horizontalCenter
|
||||
anchors.verticalCenter: root.hasImage ? undefined : image.verticalCenter
|
||||
anchors.right: root.hasImage ? image.right : undefined
|
||||
anchors.bottom: root.hasImage ? image.bottom : undefined
|
||||
|
||||
sourceComponent: AppIconBadge {
|
||||
modelData: root.modelData
|
||||
hasImage: root.hasImage
|
||||
hasAppIcon: root.hasAppIcon
|
||||
sourceComponent: StyledRect {
|
||||
radius: Appearance.rounding.full
|
||||
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) : Colours.palette.m3secondaryContainer
|
||||
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 {
|
||||
radius: Appearance.rounding.full
|
||||
color: root.modelData.getStateLayerColor()
|
||||
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
|
||||
|
||||
function onClicked() {
|
||||
root.expanded = !root.expanded;
|
||||
|
|
@ -417,7 +443,7 @@ StyledRect {
|
|||
required property var modelData
|
||||
|
||||
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.preferredHeight: actionText.height + Appearance.padding.small * 2
|
||||
|
|
@ -426,7 +452,7 @@ StyledRect {
|
|||
|
||||
StateLayer {
|
||||
radius: Appearance.rounding.full
|
||||
color: root.modelData.getStateLayerColor()
|
||||
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onSecondary : Colours.palette.m3onSurface
|
||||
|
||||
function onClicked(): void {
|
||||
action.modelData.invoke();
|
||||
|
|
@ -438,7 +464,7 @@ StyledRect {
|
|||
|
||||
anchors.centerIn: parent
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,8 +8,6 @@ Item {
|
|||
required property var visibilities
|
||||
required property Item panels
|
||||
|
||||
readonly property alias content: content
|
||||
|
||||
visible: height > 0
|
||||
implicitWidth: Math.max(panels.sidebar.width, content.implicitWidth)
|
||||
implicitHeight: content.implicitHeight
|
||||
|
|
|
|||
|
|
@ -28,13 +28,14 @@ StyledRect {
|
|||
|
||||
border.width: 1
|
||||
border.color: {
|
||||
let colour = Colours.palette.m3outlineVariant;
|
||||
if (root.modelData.type === Toast.Success)
|
||||
return Colours.palette.m3success;
|
||||
colour = Colours.palette.m3success;
|
||||
if (root.modelData.type === Toast.Warning)
|
||||
return Colours.palette.m3secondaryContainer;
|
||||
colour = Colours.palette.m3secondaryContainer;
|
||||
if (root.modelData.type === Toast.Error)
|
||||
return Colours.palette.m3error;
|
||||
return Colours.palette.m3outlineVariant;
|
||||
colour = Colours.palette.m3error;
|
||||
return Qt.alpha(colour, 0.3);
|
||||
}
|
||||
|
||||
Elevation {
|
||||
|
|
|
|||
|
|
@ -77,10 +77,8 @@ Singleton {
|
|||
onNotification: notif => {
|
||||
notif.tracked = true;
|
||||
|
||||
const shouldShowAsToast = !props.dnd && ![...Visibilities.screens.values()].some(v => v.sidebar);
|
||||
const comp = notifComp.createObject(root, {
|
||||
popup: shouldShowAsToast,
|
||||
showAsToast: shouldShowAsToast,
|
||||
popup: !props.dnd && ![...Visibilities.screens.values()].some(v => v.sidebar),
|
||||
notification: notif
|
||||
});
|
||||
root.list = [comp, ...root.list];
|
||||
|
|
@ -145,7 +143,6 @@ Singleton {
|
|||
|
||||
property bool popup
|
||||
property bool closed
|
||||
property bool showAsToast: false
|
||||
property var locks: new Set()
|
||||
|
||||
property date time: new Date()
|
||||
|
|
@ -179,74 +176,7 @@ Singleton {
|
|||
property bool hasActionIcons
|
||||
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 {
|
||||
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
|
||||
interval: notif.expireTimeout > 0 ? notif.expireTimeout : Config.notifs.defaultExpireTimeout
|
||||
onTriggered: {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue