mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Improve notification swipe gestures and dismissal animations
This commit is contained in:
@@ -211,16 +211,31 @@ Variants {
|
||||
property real scaleValue: 0.8
|
||||
property real opacityValue: 0.0
|
||||
property real slideOffset: 0
|
||||
property real swipeOffset: 0
|
||||
property real pressGlobalX: 0
|
||||
property bool isSwiping: false
|
||||
property bool suppressClick: false
|
||||
readonly property real swipeStartThreshold: Math.round(18 * Style.uiScaleRatio)
|
||||
readonly property real swipeDismissThreshold: Math.max(110, cardBackground.width * 0.32)
|
||||
|
||||
scale: scaleValue
|
||||
opacity: opacityValue
|
||||
transform: Translate {
|
||||
x: card.swipeOffset
|
||||
y: card.slideOffset
|
||||
}
|
||||
|
||||
readonly property real slideInOffset: notifWindow.isTop ? -slideDistance : slideDistance
|
||||
readonly property real slideOutOffset: slideInOffset
|
||||
|
||||
function clampSwipeDelta(deltaX) {
|
||||
if (notifWindow.isRight)
|
||||
return Math.max(0, deltaX);
|
||||
if (notifWindow.isLeft)
|
||||
return Math.min(0, deltaX);
|
||||
return deltaX;
|
||||
}
|
||||
|
||||
// Background with border
|
||||
Rectangle {
|
||||
id: cardBackground
|
||||
@@ -301,26 +316,69 @@ Variants {
|
||||
|
||||
// Right-click to dismiss
|
||||
MouseArea {
|
||||
id: cardDragArea
|
||||
anchors.fill: cardBackground
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
hoverEnabled: true
|
||||
onEntered: card.hoverCount++
|
||||
onExited: card.hoverCount--
|
||||
onClicked: mouse => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
card.animateOut();
|
||||
} else if (mouse.button === Qt.LeftButton) {
|
||||
var actions = model.actionsJson ? JSON.parse(model.actionsJson) : [];
|
||||
var hasDefault = actions.some(function (a) {
|
||||
return a.identifier === "default";
|
||||
});
|
||||
if (hasDefault) {
|
||||
card.animateOut();
|
||||
deferredActionTimer.actionId = "default";
|
||||
deferredActionTimer.start();
|
||||
}
|
||||
onPressed: mouse => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
const globalPoint = cardDragArea.mapToGlobal(mouse.x, mouse.y);
|
||||
card.pressGlobalX = globalPoint.x;
|
||||
card.isSwiping = false;
|
||||
card.suppressClick = false;
|
||||
}
|
||||
}
|
||||
onPositionChanged: mouse => {
|
||||
if (!(mouse.buttons & Qt.LeftButton) || card.isRemoving)
|
||||
return;
|
||||
const globalPoint = cardDragArea.mapToGlobal(mouse.x, mouse.y);
|
||||
const deltaX = card.clampSwipeDelta(globalPoint.x - card.pressGlobalX);
|
||||
if (!card.isSwiping) {
|
||||
if (Math.abs(deltaX) < card.swipeStartThreshold)
|
||||
return;
|
||||
card.isSwiping = true;
|
||||
}
|
||||
card.swipeOffset = deltaX;
|
||||
}
|
||||
onReleased: mouse => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
card.animateOut();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouse.button !== Qt.LeftButton)
|
||||
return;
|
||||
|
||||
if (card.isSwiping) {
|
||||
if (Math.abs(card.swipeOffset) >= card.swipeDismissThreshold) {
|
||||
card.dismissBySwipe();
|
||||
} else {
|
||||
card.swipeOffset = 0;
|
||||
}
|
||||
card.suppressClick = true;
|
||||
card.isSwiping = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (card.suppressClick)
|
||||
return;
|
||||
|
||||
var actions = model.actionsJson ? JSON.parse(model.actionsJson) : [];
|
||||
var hasDefault = actions.some(function (a) {
|
||||
return a.identifier === "default";
|
||||
});
|
||||
if (hasDefault) {
|
||||
card.animateOut();
|
||||
deferredActionTimer.actionId = "default";
|
||||
deferredActionTimer.start();
|
||||
}
|
||||
}
|
||||
onCanceled: {
|
||||
card.isSwiping = false;
|
||||
card.swipeOffset = 0;
|
||||
}
|
||||
}
|
||||
// Animation setup
|
||||
function triggerEntryAnimation() {
|
||||
@@ -329,6 +387,8 @@ Variants {
|
||||
resumeTimer.stop();
|
||||
isRemoving = false;
|
||||
hoverCount = 0;
|
||||
isSwiping = false;
|
||||
swipeOffset = 0;
|
||||
if (Settings.data.general.animationDisabled) {
|
||||
slideOffset = 0;
|
||||
scaleValue = 1.0;
|
||||
@@ -366,6 +426,8 @@ Variants {
|
||||
animInDelayTimer.stop();
|
||||
resumeTimer.stop();
|
||||
isRemoving = true;
|
||||
isSwiping = false;
|
||||
swipeOffset = 0;
|
||||
if (!Settings.data.general.animationDisabled) {
|
||||
slideOffset = slideOutOffset;
|
||||
scaleValue = 0.8;
|
||||
@@ -373,6 +435,22 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
function dismissBySwipe() {
|
||||
if (isRemoving)
|
||||
return;
|
||||
animInDelayTimer.stop();
|
||||
resumeTimer.stop();
|
||||
isRemoving = true;
|
||||
isSwiping = false;
|
||||
if (!Settings.data.general.animationDisabled) {
|
||||
swipeOffset = swipeOffset >= 0 ? cardBackground.width + Style.marginXL : -cardBackground.width - Style.marginXL;
|
||||
scaleValue = 0.8;
|
||||
opacityValue = 0.0;
|
||||
} else {
|
||||
swipeOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: removalTimer
|
||||
interval: Style.animationSlow
|
||||
@@ -430,6 +508,14 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on swipeOffset {
|
||||
enabled: !Settings.data.general.animationDisabled && !card.isSwiping
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Content
|
||||
ColumnLayout {
|
||||
id: notificationContent
|
||||
|
||||
Reference in New Issue
Block a user