1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-28 15:32:50 -05:00

notifications: add swipe to dismiss functionality

fixes #927
This commit is contained in:
bbedward
2025-12-12 14:39:51 -05:00
parent e95f7ce367
commit 0ff9fdb365
2 changed files with 335 additions and 159 deletions

View File

@@ -18,12 +18,12 @@ DankListView {
onIsUserScrollingChanged: { onIsUserScrollingChanged: {
if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) { if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) {
autoScrollDisabled = true autoScrollDisabled = true;
} }
} }
function enableAutoScroll() { function enableAutoScroll() {
autoScrollDisabled = false autoScrollDisabled = false;
} }
Timer { Timer {
@@ -33,7 +33,7 @@ DankListView {
repeat: true repeat: true
onTriggered: { onTriggered: {
if (keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled) { if (keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled) {
keyboardController.ensureVisible() keyboardController.ensureVisible();
} }
} }
} }
@@ -46,48 +46,105 @@ DankListView {
onModelChanged: { onModelChanged: {
if (!keyboardController || !keyboardController.keyboardNavigationActive) { if (!keyboardController || !keyboardController.keyboardNavigationActive) {
return return;
} }
keyboardController.rebuildFlatNavigation() keyboardController.rebuildFlatNavigation();
Qt.callLater(() => { Qt.callLater(() => {
if (keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled) { if (keyboardController && keyboardController.keyboardNavigationActive && !autoScrollDisabled) {
keyboardController.ensureVisible() keyboardController.ensureVisible();
} }
}) });
} }
delegate: Item { delegate: Item {
id: delegateRoot
required property var modelData required property var modelData
required property int index required property int index
readonly property bool isExpanded: (NotificationService.expandedGroups[modelData && modelData.key] || false) readonly property bool isExpanded: (NotificationService.expandedGroups[modelData && modelData.key] || false)
property real swipeOffset: 0
property bool isDismissing: false
readonly property real dismissThreshold: width * 0.35
width: ListView.view.width width: ListView.view.width
height: notificationCard.height height: isDismissing ? 0 : notificationCard.height
clip: true
Behavior on height {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
NotificationCard { NotificationCard {
id: notificationCard id: notificationCard
width: parent.width width: parent.width
x: delegateRoot.swipeOffset
notificationGroup: modelData notificationGroup: modelData
keyboardNavigationActive: listView.keyboardActive keyboardNavigationActive: listView.keyboardActive
opacity: 1 - Math.abs(delegateRoot.swipeOffset) / (delegateRoot.width * 0.5)
isGroupSelected: { isGroupSelected: {
if (!keyboardController || !keyboardController.keyboardNavigationActive || !listView.keyboardActive) { if (!keyboardController || !keyboardController.keyboardNavigationActive || !listView.keyboardActive)
return false return false;
} keyboardController.selectionVersion;
keyboardController.selectionVersion const selection = keyboardController.getCurrentSelection();
const selection = keyboardController.getCurrentSelection() return selection.type === "group" && selection.groupIndex === index;
return selection.type === "group" && selection.groupIndex === index
} }
selectedNotificationIndex: { selectedNotificationIndex: {
if (!keyboardController || !keyboardController.keyboardNavigationActive || !listView.keyboardActive) { if (!keyboardController || !keyboardController.keyboardNavigationActive || !listView.keyboardActive)
return -1 return -1;
} keyboardController.selectionVersion;
keyboardController.selectionVersion const selection = keyboardController.getCurrentSelection();
const selection = keyboardController.getCurrentSelection() return (selection.type === "notification" && selection.groupIndex === index) ? selection.notificationIndex : -1;
return (selection.type === "notification" && selection.groupIndex === index) ? selection.notificationIndex : -1
} }
Behavior on x {
enabled: !swipeDragHandler.active
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
}
}
}
DragHandler {
id: swipeDragHandler
target: null
yAxis.enabled: false
xAxis.enabled: true
onActiveChanged: {
if (active || delegateRoot.isDismissing)
return;
if (Math.abs(delegateRoot.swipeOffset) > delegateRoot.dismissThreshold) {
delegateRoot.isDismissing = true;
delegateRoot.swipeOffset = delegateRoot.swipeOffset > 0 ? delegateRoot.width : -delegateRoot.width;
dismissTimer.start();
} else {
delegateRoot.swipeOffset = 0;
}
}
onTranslationChanged: {
if (delegateRoot.isDismissing)
return;
delegateRoot.swipeOffset = translation.x;
}
}
Timer {
id: dismissTimer
interval: Theme.shortDuration
onTriggered: NotificationService.dismissGroup(delegateRoot.modelData?.key || "")
} }
} }
@@ -96,42 +153,42 @@ DankListView {
function onGroupedNotificationsChanged() { function onGroupedNotificationsChanged() {
if (!keyboardController) { if (!keyboardController) {
return return;
} }
if (keyboardController.isTogglingGroup) { if (keyboardController.isTogglingGroup) {
keyboardController.rebuildFlatNavigation() keyboardController.rebuildFlatNavigation();
return return;
} }
keyboardController.rebuildFlatNavigation() keyboardController.rebuildFlatNavigation();
if (keyboardController.keyboardNavigationActive) { if (keyboardController.keyboardNavigationActive) {
Qt.callLater(() => { Qt.callLater(() => {
if (!autoScrollDisabled) { if (!autoScrollDisabled) {
keyboardController.ensureVisible() keyboardController.ensureVisible();
} }
}) });
} }
} }
function onExpandedGroupsChanged() { function onExpandedGroupsChanged() {
if (keyboardController && keyboardController.keyboardNavigationActive) { if (keyboardController && keyboardController.keyboardNavigationActive) {
Qt.callLater(() => { Qt.callLater(() => {
if (!autoScrollDisabled) { if (!autoScrollDisabled) {
keyboardController.ensureVisible() keyboardController.ensureVisible();
} }
}) });
} }
} }
function onExpandedMessagesChanged() { function onExpandedMessagesChanged() {
if (keyboardController && keyboardController.keyboardNavigationActive) { if (keyboardController && keyboardController.keyboardNavigationActive) {
Qt.callLater(() => { Qt.callLater(() => {
if (!autoScrollDisabled) { if (!autoScrollDisabled) {
keyboardController.ensureVisible() keyboardController.ensureVisible();
} }
}) });
} }
} }
} }

View File

@@ -4,7 +4,6 @@ import QtQuick.Effects
import QtQuick.Shapes import QtQuick.Shapes
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Widgets
import Quickshell.Services.Notifications import Quickshell.Services.Notifications
import qs.Common import qs.Common
import qs.Services import qs.Services
@@ -29,63 +28,63 @@ PanelWindow {
function startExit() { function startExit() {
if (exiting || _isDestroying) { if (exiting || _isDestroying) {
return return;
} }
exiting = true exiting = true;
exitAnim.restart() exitAnim.restart();
exitWatchdog.restart() exitWatchdog.restart();
if (NotificationService.removeFromVisibleNotifications) if (NotificationService.removeFromVisibleNotifications)
NotificationService.removeFromVisibleNotifications(win.notificationData) NotificationService.removeFromVisibleNotifications(win.notificationData);
} }
function forceExit() { function forceExit() {
if (_isDestroying) { if (_isDestroying) {
return return;
} }
_isDestroying = true _isDestroying = true;
exiting = true exiting = true;
visible = false visible = false;
exitWatchdog.stop() exitWatchdog.stop();
finalizeExit("forced") finalizeExit("forced");
} }
function finalizeExit(reason) { function finalizeExit(reason) {
if (_finalized) { if (_finalized) {
return return;
} }
_finalized = true _finalized = true;
_isDestroying = true _isDestroying = true;
exitWatchdog.stop() exitWatchdog.stop();
wrapperConn.enabled = false wrapperConn.enabled = false;
wrapperConn.target = null wrapperConn.target = null;
win.exitFinished() win.exitFinished();
} }
visible: hasValidData visible: hasValidData
WlrLayershell.layer: { WlrLayershell.layer: {
const envLayer = Quickshell.env("DMS_NOTIFICATION_LAYER") const envLayer = Quickshell.env("DMS_NOTIFICATION_LAYER");
if (envLayer) { if (envLayer) {
switch (envLayer) { switch (envLayer) {
case "bottom": case "bottom":
return WlrLayershell.Bottom return WlrLayershell.Bottom;
case "overlay": case "overlay":
return WlrLayershell.Overlay return WlrLayershell.Overlay;
case "background": case "background":
return WlrLayershell.Background return WlrLayershell.Background;
case "top": case "top":
return WlrLayershell.Top return WlrLayershell.Top;
} }
} }
if (!notificationData) if (!notificationData)
return WlrLayershell.Top return WlrLayershell.Top;
SettingsData.notificationOverlayEnabled SettingsData.notificationOverlayEnabled;
const shouldUseOverlay = (SettingsData.notificationOverlayEnabled) || (notificationData.urgency === NotificationUrgency.Critical) const shouldUseOverlay = (SettingsData.notificationOverlayEnabled) || (notificationData.urgency === NotificationUrgency.Critical);
return shouldUseOverlay ? WlrLayershell.Overlay : WlrLayershell.Top return shouldUseOverlay ? WlrLayershell.Overlay : WlrLayershell.Top;
} }
WlrLayershell.exclusiveZone: -1 WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
@@ -94,32 +93,32 @@ PanelWindow {
implicitHeight: 122 implicitHeight: 122
onHasValidDataChanged: { onHasValidDataChanged: {
if (!hasValidData && !exiting && !_isDestroying) { if (!hasValidData && !exiting && !_isDestroying) {
forceExit() forceExit();
} }
} }
Component.onCompleted: { Component.onCompleted: {
if (hasValidData) { if (hasValidData) {
Qt.callLater(() => enterX.restart()) Qt.callLater(() => enterX.restart());
} else { } else {
forceExit() forceExit();
} }
} }
onNotificationDataChanged: { onNotificationDataChanged: {
if (!_isDestroying) { if (!_isDestroying) {
wrapperConn.target = win.notificationData || null wrapperConn.target = win.notificationData || null;
notificationConn.target = (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null notificationConn.target = (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null;
} }
} }
onEntered: { onEntered: {
if (!_isDestroying) { if (!_isDestroying) {
enterDelay.start() enterDelay.start();
} }
} }
Component.onDestruction: { Component.onDestruction: {
_isDestroying = true _isDestroying = true;
exitWatchdog.stop() exitWatchdog.stop();
if (notificationData && notificationData.timer) { if (notificationData && notificationData.timer) {
notificationData.timer.stop() notificationData.timer.stop();
} }
} }
@@ -138,54 +137,66 @@ PanelWindow {
} }
function getBarInfo() { function getBarInfo() {
if (!screen) return { topBar: 0, bottomBar: 0, leftBar: 0, rightBar: 0 } if (!screen)
return {
topBar: 0,
bottomBar: 0,
leftBar: 0,
rightBar: 0
};
return SettingsData.getAdjacentBarInfo(screen, SettingsData.notificationPopupPosition, { return SettingsData.getAdjacentBarInfo(screen, SettingsData.notificationPopupPosition, {
id: "notification-popup", id: "notification-popup",
screenPreferences: [screen.name], screenPreferences: [screen.name],
autoHide: false autoHide: false
}) });
} }
function getTopMargin() { function getTopMargin() {
const popupPos = SettingsData.notificationPopupPosition const popupPos = SettingsData.notificationPopupPosition;
const isTop = isTopCenter || popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Left const isTop = isTopCenter || popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Left;
if (!isTop) return 0 if (!isTop)
return 0;
const barInfo = getBarInfo() const barInfo = getBarInfo();
const base = barInfo.topBar > 0 ? barInfo.topBar : Theme.popupDistance const base = barInfo.topBar > 0 ? barInfo.topBar : Theme.popupDistance;
return base + screenY return base + screenY;
} }
function getBottomMargin() { function getBottomMargin() {
const popupPos = SettingsData.notificationPopupPosition const popupPos = SettingsData.notificationPopupPosition;
const isBottom = popupPos === SettingsData.Position.Bottom || popupPos === SettingsData.Position.Right const isBottom = popupPos === SettingsData.Position.Bottom || popupPos === SettingsData.Position.Right;
if (!isBottom) return 0 if (!isBottom)
return 0;
const barInfo = getBarInfo() const barInfo = getBarInfo();
const base = barInfo.bottomBar > 0 ? barInfo.bottomBar : Theme.popupDistance const base = barInfo.bottomBar > 0 ? barInfo.bottomBar : Theme.popupDistance;
return base + screenY return base + screenY;
} }
function getLeftMargin() { function getLeftMargin() {
if (isTopCenter) return (screen.width - implicitWidth) / 2 if (isTopCenter)
return (screen.width - implicitWidth) / 2;
const popupPos = SettingsData.notificationPopupPosition const popupPos = SettingsData.notificationPopupPosition;
const isLeft = popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom const isLeft = popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom;
if (!isLeft) return 0 if (!isLeft)
return 0;
const barInfo = getBarInfo() const barInfo = getBarInfo();
return barInfo.leftBar > 0 ? barInfo.leftBar : Theme.popupDistance return barInfo.leftBar > 0 ? barInfo.leftBar : Theme.popupDistance;
} }
function getRightMargin() { function getRightMargin() {
if (isTopCenter) return 0 if (isTopCenter)
return 0;
const popupPos = SettingsData.notificationPopupPosition const popupPos = SettingsData.notificationPopupPosition;
const isRight = popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Right const isRight = popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Right;
if (!isRight) return 0 if (!isRight)
return 0;
const barInfo = getBarInfo() const barInfo = getBarInfo();
return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance;
} }
readonly property real dpr: CompositorService.getScreenScale(win.screen) readonly property real dpr: CompositorService.getScreenScale(win.screen)
@@ -201,6 +212,11 @@ PanelWindow {
height: alignedHeight height: alignedHeight
visible: win.hasValidData visible: win.hasValidData
property real swipeOffset: 0
readonly property real dismissThreshold: isTopCenter ? height * 0.4 : width * 0.35
readonly property bool swipeActive: swipeDragHandler.active
property bool swipeDismissing: false
property real shadowBlurPx: 10 property real shadowBlurPx: 10
property real shadowSpreadPx: 0 property real shadowSpreadPx: 0
property real shadowBaseAlpha: 0.60 property real shadowBaseAlpha: 0.60
@@ -227,8 +243,8 @@ PanelWindow {
shadowBlur: Math.max(0, Math.min(1, content.shadowBlurPx / bgShadowLayer.blurMax)) shadowBlur: Math.max(0, Math.min(1, content.shadowBlurPx / bgShadowLayer.blurMax))
shadowScale: 1 + (2 * content.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height)) shadowScale: 1 + (2 * content.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
shadowColor: { shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
return Theme.withAlpha(baseColor, content.effectiveShadowAlpha) return Theme.withAlpha(baseColor, content.effectiveShadowAlpha);
} }
} }
@@ -250,14 +266,46 @@ PanelWindow {
startX: backgroundShape.radius startX: backgroundShape.radius
startY: 0 startY: 0
PathLine { x: backgroundShape.width - backgroundShape.radius; y: 0 } PathLine {
PathQuad { x: backgroundShape.width; y: backgroundShape.radius; controlX: backgroundShape.width; controlY: 0 } x: backgroundShape.width - backgroundShape.radius
PathLine { x: backgroundShape.width; y: backgroundShape.height - backgroundShape.radius } y: 0
PathQuad { x: backgroundShape.width - backgroundShape.radius; y: backgroundShape.height; controlX: backgroundShape.width; controlY: backgroundShape.height } }
PathLine { x: backgroundShape.radius; y: backgroundShape.height } PathQuad {
PathQuad { x: 0; y: backgroundShape.height - backgroundShape.radius; controlX: 0; controlY: backgroundShape.height } x: backgroundShape.width
PathLine { x: 0; y: backgroundShape.radius } y: backgroundShape.radius
PathQuad { x: backgroundShape.radius; y: 0; controlX: 0; controlY: 0 } controlX: backgroundShape.width
controlY: 0
}
PathLine {
x: backgroundShape.width
y: backgroundShape.height - backgroundShape.radius
}
PathQuad {
x: backgroundShape.width - backgroundShape.radius
y: backgroundShape.height
controlX: backgroundShape.width
controlY: backgroundShape.height
}
PathLine {
x: backgroundShape.radius
y: backgroundShape.height
}
PathQuad {
x: 0
y: backgroundShape.height - backgroundShape.radius
controlX: 0
controlY: backgroundShape.height
}
PathLine {
x: 0
y: backgroundShape.radius
}
PathQuad {
x: backgroundShape.radius
y: 0
controlX: 0
controlY: 0
}
} }
} }
@@ -318,26 +366,26 @@ PanelWindow {
imageSource: { imageSource: {
if (!notificationData) if (!notificationData)
return "" return "";
if (hasNotificationImage) if (hasNotificationImage)
return notificationData.cleanImage || "" return notificationData.cleanImage || "";
if (notificationData.appIcon) { if (notificationData.appIcon) {
const appIcon = notificationData.appIcon const appIcon = notificationData.appIcon;
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://")) if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://"))
return appIcon return appIcon;
return Quickshell.iconPath(appIcon, true) return Quickshell.iconPath(appIcon, true);
} }
return "" return "";
} }
hasImage: hasNotificationImage hasImage: hasNotificationImage
fallbackIcon: "" fallbackIcon: ""
fallbackText: { fallbackText: {
const appName = notificationData?.appName || "?" const appName = notificationData?.appName || "?";
return appName.charAt(0).toUpperCase() return appName.charAt(0).toUpperCase();
} }
} }
@@ -367,14 +415,14 @@ PanelWindow {
width: parent.width width: parent.width
text: { text: {
if (!notificationData) if (!notificationData)
return "" return "";
const appName = notificationData.appName || "" const appName = notificationData.appName || "";
const timeStr = notificationData.timeStr || "" const timeStr = notificationData.timeStr || "";
if (timeStr.length > 0) if (timeStr.length > 0)
return appName + " • " + timeStr return appName + " • " + timeStr;
else else
return appName return appName;
} }
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
@@ -405,8 +453,8 @@ PanelWindow {
visible: text.length > 0 visible: text.length > 0
linkColor: Theme.primary linkColor: Theme.primary
onLinkActivated: link => { onLinkActivated: link => {
return Qt.openUrlExternally(link) return Qt.openUrlExternally(link);
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
@@ -432,7 +480,7 @@ PanelWindow {
z: 15 z: 15
onClicked: { onClicked: {
if (notificationData && !win.exiting) if (notificationData && !win.exiting)
notificationData.popup = false notificationData.popup = false;
} }
} }
@@ -475,10 +523,10 @@ PanelWindow {
onExited: parent.isHovered = false onExited: parent.isHovered = false
onClicked: { onClicked: {
if (modelData && modelData.invoke) if (modelData && modelData.invoke)
modelData.invoke() modelData.invoke();
if (notificationData && !win.exiting) if (notificationData && !win.exiting)
notificationData.popup = false notificationData.popup = false;
} }
} }
} }
@@ -519,7 +567,7 @@ PanelWindow {
onExited: clearButton.isHovered = false onExited: clearButton.isHovered = false
onClicked: { onClicked: {
if (notificationData && !win.exiting) if (notificationData && !win.exiting)
NotificationService.dismissNotification(notificationData) NotificationService.dismissNotification(notificationData);
} }
} }
} }
@@ -534,40 +582,108 @@ PanelWindow {
z: -1 z: -1
onEntered: { onEntered: {
if (notificationData && notificationData.timer) if (notificationData && notificationData.timer)
notificationData.timer.stop() notificationData.timer.stop();
} }
onExited: { onExited: {
if (notificationData && notificationData.popup && notificationData.timer) if (notificationData && notificationData.popup && notificationData.timer)
notificationData.timer.restart() notificationData.timer.restart();
} }
onClicked: (mouse) => { onClicked: mouse => {
if (!notificationData || win.exiting) if (!notificationData || win.exiting)
return return;
if (mouse.button === Qt.RightButton) { if (mouse.button === Qt.RightButton) {
NotificationService.dismissNotification(notificationData) NotificationService.dismissNotification(notificationData);
} else if (mouse.button === Qt.LeftButton) { } else if (mouse.button === Qt.LeftButton) {
if (notificationData.actions && notificationData.actions.length > 0) { if (notificationData.actions && notificationData.actions.length > 0) {
notificationData.actions[0].invoke() notificationData.actions[0].invoke();
NotificationService.dismissNotification(notificationData) NotificationService.dismissNotification(notificationData);
} else { } else {
notificationData.popup = false notificationData.popup = false;
} }
} }
} }
} }
} }
transform: Translate { DragHandler {
id: tx id: swipeDragHandler
target: null
xAxis.enabled: !isTopCenter
yAxis.enabled: isTopCenter
x: { onActiveChanged: {
if (isTopCenter) return 0 if (active || win.exiting || content.swipeDismissing)
const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom return;
return isLeft ? -Anims.slidePx : Anims.slidePx
if (Math.abs(content.swipeOffset) > content.dismissThreshold) {
content.swipeDismissing = true;
swipeDismissAnim.start();
} else {
content.swipeOffset = 0;
}
}
onTranslationChanged: {
if (win.exiting)
return;
const raw = isTopCenter ? translation.y : translation.x;
if (isTopCenter) {
content.swipeOffset = Math.min(0, raw);
} else {
const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom;
content.swipeOffset = isLeft ? Math.min(0, raw) : Math.max(0, raw);
}
} }
y: isTopCenter ? -Anims.slidePx : 0
} }
opacity: 1 - Math.abs(content.swipeOffset) / (isTopCenter ? content.height : content.width * 0.6)
Behavior on opacity {
enabled: !content.swipeActive
NumberAnimation {
duration: Theme.shortDuration
}
}
Behavior on swipeOffset {
enabled: !content.swipeActive && !content.swipeDismissing
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
NumberAnimation {
id: swipeDismissAnim
target: content
property: "swipeOffset"
to: isTopCenter ? -content.height : (SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom ? -content.width : content.width)
duration: Anims.durShort
easing.type: Easing.OutCubic
onStopped: {
NotificationService.dismissNotification(notificationData);
win.forceExit();
}
}
transform: [
Translate {
id: swipeTx
x: isTopCenter ? 0 : content.swipeOffset
y: isTopCenter ? content.swipeOffset : 0
},
Translate {
id: tx
x: {
if (isTopCenter)
return 0;
const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom;
return isLeft ? -Anims.slidePx : Anims.slidePx;
}
y: isTopCenter ? -Anims.slidePx : 0
}
]
} }
NumberAnimation { NumberAnimation {
@@ -576,9 +692,10 @@ PanelWindow {
target: tx target: tx
property: isTopCenter ? "y" : "x" property: isTopCenter ? "y" : "x"
from: { from: {
if (isTopCenter) return -Anims.slidePx if (isTopCenter)
const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom return -Anims.slidePx;
return isLeft ? -Anims.slidePx : Anims.slidePx const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom;
return isLeft ? -Anims.slidePx : Anims.slidePx;
} }
to: 0 to: 0
duration: Anims.durMed duration: Anims.durMed
@@ -587,9 +704,11 @@ PanelWindow {
onStopped: { onStopped: {
if (!win.exiting && !win._isDestroying) { if (!win.exiting && !win._isDestroying) {
if (isTopCenter) { if (isTopCenter) {
if (Math.abs(tx.y) < 0.5) win.entered() if (Math.abs(tx.y) < 0.5)
win.entered();
} else { } else {
if (Math.abs(tx.x) < 0.5) win.entered() if (Math.abs(tx.x) < 0.5)
win.entered();
} }
} }
} }
@@ -605,9 +724,10 @@ PanelWindow {
property: isTopCenter ? "y" : "x" property: isTopCenter ? "y" : "x"
from: 0 from: 0
to: { to: {
if (isTopCenter) return -Anims.slidePx if (isTopCenter)
const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom return -Anims.slidePx;
return isLeft ? -Anims.slidePx : Anims.slidePx const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom;
return isLeft ? -Anims.slidePx : Anims.slidePx;
} }
duration: Anims.durShort duration: Anims.durShort
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
@@ -640,10 +760,9 @@ PanelWindow {
function onPopupChanged() { function onPopupChanged() {
if (!win.notificationData || win._isDestroying) if (!win.notificationData || win._isDestroying)
return return;
if (!win.notificationData.popup && !win.exiting) if (!win.notificationData.popup && !win.exiting)
startExit() startExit();
} }
target: win.notificationData || null target: win.notificationData || null
@@ -656,7 +775,7 @@ PanelWindow {
function onDropped() { function onDropped() {
if (!win._isDestroying && !win.exiting) if (!win._isDestroying && !win.exiting)
forceExit() forceExit();
} }
target: (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null target: (win.notificationData && win.notificationData.notification && win.notificationData.notification.Retainable) || null
@@ -671,7 +790,7 @@ PanelWindow {
repeat: false repeat: false
onTriggered: { onTriggered: {
if (notificationData && notificationData.timer && !exiting && !_isDestroying) if (notificationData && notificationData.timer && !exiting && !_isDestroying)
notificationData.timer.start() notificationData.timer.start();
} }
} }