mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Use vertical swipe dismiss for top/bottom centered notifications
This commit is contained in:
@@ -212,17 +212,21 @@ Variants {
|
||||
property real opacityValue: 0.0
|
||||
property real slideOffset: 0
|
||||
property real swipeOffset: 0
|
||||
property real swipeOffsetY: 0
|
||||
property real pressGlobalX: 0
|
||||
property real pressGlobalY: 0
|
||||
property bool isSwiping: false
|
||||
property bool suppressClick: false
|
||||
readonly property bool useVerticalSwipe: notifWindow.location === "bottom" || notifWindow.location === "top"
|
||||
readonly property real swipeStartThreshold: Math.round(18 * Style.uiScaleRatio)
|
||||
readonly property real swipeDismissThreshold: Math.max(110, cardBackground.width * 0.32)
|
||||
readonly property real verticalSwipeDismissThreshold: Math.max(70, cardBackground.height * 0.35)
|
||||
|
||||
scale: scaleValue
|
||||
opacity: opacityValue
|
||||
transform: Translate {
|
||||
x: card.swipeOffset
|
||||
y: card.slideOffset
|
||||
y: card.slideOffset + card.swipeOffsetY
|
||||
}
|
||||
|
||||
readonly property real slideInOffset: notifWindow.isTop ? -slideDistance : slideDistance
|
||||
@@ -236,6 +240,14 @@ Variants {
|
||||
return deltaX;
|
||||
}
|
||||
|
||||
function clampVerticalSwipeDelta(deltaY) {
|
||||
if (notifWindow.isBottom)
|
||||
return Math.max(0, deltaY);
|
||||
if (notifWindow.isTop)
|
||||
return Math.min(0, deltaY);
|
||||
return deltaY;
|
||||
}
|
||||
|
||||
// Background with border
|
||||
Rectangle {
|
||||
id: cardBackground
|
||||
@@ -326,6 +338,7 @@ Variants {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
const globalPoint = cardDragArea.mapToGlobal(mouse.x, mouse.y);
|
||||
card.pressGlobalX = globalPoint.x;
|
||||
card.pressGlobalY = globalPoint.y;
|
||||
card.isSwiping = false;
|
||||
card.suppressClick = false;
|
||||
}
|
||||
@@ -334,13 +347,28 @@ Variants {
|
||||
if (!(mouse.buttons & Qt.LeftButton) || card.isRemoving)
|
||||
return;
|
||||
const globalPoint = cardDragArea.mapToGlobal(mouse.x, mouse.y);
|
||||
const deltaX = card.clampSwipeDelta(globalPoint.x - card.pressGlobalX);
|
||||
const rawDeltaX = globalPoint.x - card.pressGlobalX;
|
||||
const rawDeltaY = globalPoint.y - card.pressGlobalY;
|
||||
const deltaX = card.clampSwipeDelta(rawDeltaX);
|
||||
const deltaY = card.clampVerticalSwipeDelta(rawDeltaY);
|
||||
if (!card.isSwiping) {
|
||||
if (card.useVerticalSwipe) {
|
||||
if (Math.abs(deltaY) < card.swipeStartThreshold)
|
||||
return;
|
||||
card.isSwiping = true;
|
||||
} else {
|
||||
if (Math.abs(deltaX) < card.swipeStartThreshold)
|
||||
return;
|
||||
card.isSwiping = true;
|
||||
}
|
||||
}
|
||||
if (card.useVerticalSwipe) {
|
||||
card.swipeOffset = 0;
|
||||
card.swipeOffsetY = deltaY;
|
||||
} else {
|
||||
card.swipeOffset = deltaX;
|
||||
card.swipeOffsetY = 0;
|
||||
}
|
||||
}
|
||||
onReleased: mouse => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
@@ -352,10 +380,13 @@ Variants {
|
||||
return;
|
||||
|
||||
if (card.isSwiping) {
|
||||
if (Math.abs(card.swipeOffset) >= card.swipeDismissThreshold) {
|
||||
const dismissDistance = card.useVerticalSwipe ? Math.abs(card.swipeOffsetY) : Math.abs(card.swipeOffset);
|
||||
const threshold = card.useVerticalSwipe ? card.verticalSwipeDismissThreshold : card.swipeDismissThreshold;
|
||||
if (dismissDistance >= threshold) {
|
||||
card.dismissBySwipe();
|
||||
} else {
|
||||
card.swipeOffset = 0;
|
||||
card.swipeOffsetY = 0;
|
||||
}
|
||||
card.suppressClick = true;
|
||||
card.isSwiping = false;
|
||||
@@ -378,6 +409,7 @@ Variants {
|
||||
onCanceled: {
|
||||
card.isSwiping = false;
|
||||
card.swipeOffset = 0;
|
||||
card.swipeOffsetY = 0;
|
||||
}
|
||||
}
|
||||
// Animation setup
|
||||
@@ -389,6 +421,7 @@ Variants {
|
||||
hoverCount = 0;
|
||||
isSwiping = false;
|
||||
swipeOffset = 0;
|
||||
swipeOffsetY = 0;
|
||||
if (Settings.data.general.animationDisabled) {
|
||||
slideOffset = 0;
|
||||
scaleValue = 1.0;
|
||||
@@ -428,6 +461,7 @@ Variants {
|
||||
isRemoving = true;
|
||||
isSwiping = false;
|
||||
swipeOffset = 0;
|
||||
swipeOffsetY = 0;
|
||||
if (!Settings.data.general.animationDisabled) {
|
||||
slideOffset = slideOutOffset;
|
||||
scaleValue = 0.8;
|
||||
@@ -443,11 +477,18 @@ Variants {
|
||||
isRemoving = true;
|
||||
isSwiping = false;
|
||||
if (!Settings.data.general.animationDisabled) {
|
||||
if (useVerticalSwipe) {
|
||||
swipeOffset = 0;
|
||||
swipeOffsetY = swipeOffsetY >= 0 ? cardBackground.height + Style.marginXL : -cardBackground.height - Style.marginXL;
|
||||
} else {
|
||||
swipeOffset = swipeOffset >= 0 ? cardBackground.width + Style.marginXL : -cardBackground.width - Style.marginXL;
|
||||
swipeOffsetY = 0;
|
||||
}
|
||||
scaleValue = 0.8;
|
||||
opacityValue = 0.0;
|
||||
} else {
|
||||
swipeOffset = 0;
|
||||
swipeOffsetY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,6 +557,14 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on swipeOffsetY {
|
||||
enabled: !Settings.data.general.animationDisabled && !card.isSwiping
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Content
|
||||
ColumnLayout {
|
||||
id: notificationContent
|
||||
|
||||
+46
-2
@@ -31,16 +31,21 @@ Item {
|
||||
property real progress: 1.0
|
||||
property int hoverCount: 0
|
||||
property real swipeOffset: 0
|
||||
property real swipeOffsetY: 0
|
||||
property real pressGlobalX: 0
|
||||
property real pressGlobalY: 0
|
||||
property bool isSwiping: false
|
||||
readonly property string location: Settings.data.notifications?.location || "top_right"
|
||||
readonly property bool isLeft: location.endsWith("_left")
|
||||
readonly property bool isRight: location.endsWith("_right")
|
||||
readonly property bool useVerticalSwipe: location === "bottom" || location === "top"
|
||||
readonly property real swipeStartThreshold: Math.round(18 * Style.uiScaleRatio)
|
||||
readonly property real swipeDismissThreshold: Math.max(110, background.width * 0.32)
|
||||
readonly property real verticalSwipeDismissThreshold: Math.max(70, background.height * 0.35)
|
||||
|
||||
transform: Translate {
|
||||
x: root.swipeOffset
|
||||
y: root.swipeOffsetY
|
||||
}
|
||||
|
||||
function clampSwipeDelta(deltaX) {
|
||||
@@ -51,6 +56,14 @@ Item {
|
||||
return deltaX;
|
||||
}
|
||||
|
||||
function clampVerticalSwipeDelta(deltaY) {
|
||||
if (location === "bottom")
|
||||
return Math.max(0, deltaY);
|
||||
if (location === "top")
|
||||
return Math.min(0, deltaY);
|
||||
return deltaY;
|
||||
}
|
||||
|
||||
onHoverCountChanged: {
|
||||
if (hoverCount > 0) {
|
||||
resumeTimer.stop();
|
||||
@@ -176,6 +189,14 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on swipeOffsetY {
|
||||
enabled: !root.isSwiping
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hideAnimation
|
||||
interval: Style.animationFast
|
||||
@@ -206,29 +227,48 @@ Item {
|
||||
onPressed: mouse => {
|
||||
const globalPoint = toastDragArea.mapToGlobal(mouse.x, mouse.y);
|
||||
root.pressGlobalX = globalPoint.x;
|
||||
root.pressGlobalY = globalPoint.y;
|
||||
root.isSwiping = false;
|
||||
}
|
||||
onPositionChanged: mouse => {
|
||||
if (!(mouse.buttons & Qt.LeftButton))
|
||||
return;
|
||||
const globalPoint = toastDragArea.mapToGlobal(mouse.x, mouse.y);
|
||||
const deltaX = root.clampSwipeDelta(globalPoint.x - root.pressGlobalX);
|
||||
const rawDeltaX = globalPoint.x - root.pressGlobalX;
|
||||
const rawDeltaY = globalPoint.y - root.pressGlobalY;
|
||||
const deltaX = root.clampSwipeDelta(rawDeltaX);
|
||||
const deltaY = root.clampVerticalSwipeDelta(rawDeltaY);
|
||||
if (!root.isSwiping) {
|
||||
if (root.useVerticalSwipe) {
|
||||
if (Math.abs(deltaY) < root.swipeStartThreshold)
|
||||
return;
|
||||
root.isSwiping = true;
|
||||
} else {
|
||||
if (Math.abs(deltaX) < root.swipeStartThreshold)
|
||||
return;
|
||||
root.isSwiping = true;
|
||||
}
|
||||
}
|
||||
if (root.useVerticalSwipe) {
|
||||
root.swipeOffset = 0;
|
||||
root.swipeOffsetY = deltaY;
|
||||
} else {
|
||||
root.swipeOffset = deltaX;
|
||||
root.swipeOffsetY = 0;
|
||||
}
|
||||
}
|
||||
onReleased: mouse => {
|
||||
if (mouse.button !== Qt.LeftButton)
|
||||
return;
|
||||
if (root.isSwiping) {
|
||||
root.isSwiping = false;
|
||||
if (Math.abs(root.swipeOffset) >= root.swipeDismissThreshold) {
|
||||
const dismissDistance = root.useVerticalSwipe ? Math.abs(root.swipeOffsetY) : Math.abs(root.swipeOffset);
|
||||
const threshold = root.useVerticalSwipe ? root.verticalSwipeDismissThreshold : root.swipeDismissThreshold;
|
||||
if (dismissDistance >= threshold) {
|
||||
root.hide();
|
||||
} else {
|
||||
root.swipeOffset = 0;
|
||||
root.swipeOffsetY = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -237,6 +277,7 @@ Item {
|
||||
onCanceled: {
|
||||
root.isSwiping = false;
|
||||
root.swipeOffset = 0;
|
||||
root.swipeOffsetY = 0;
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
@@ -345,6 +386,7 @@ Item {
|
||||
hoverCount = 0;
|
||||
isSwiping = false;
|
||||
swipeOffset = 0;
|
||||
swipeOffsetY = 0;
|
||||
|
||||
// Configure and start animation
|
||||
progressAnimation.duration = duration;
|
||||
@@ -357,6 +399,7 @@ Item {
|
||||
progressAnimation.stop();
|
||||
isSwiping = false;
|
||||
swipeOffset = 0;
|
||||
swipeOffsetY = 0;
|
||||
opacity = 0;
|
||||
scale = initialScale;
|
||||
hideAnimation.restart();
|
||||
@@ -367,6 +410,7 @@ Item {
|
||||
progressAnimation.stop();
|
||||
isSwiping = false;
|
||||
swipeOffset = 0;
|
||||
swipeOffsetY = 0;
|
||||
opacity = 0;
|
||||
scale = initialScale;
|
||||
root.hidden();
|
||||
|
||||
Reference in New Issue
Block a user