From 1c83ce1e7983e89fab866474246e342f6b0b1192 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 2 Jan 2022 06:22:27 +0100 Subject: [PATCH] Simplify Ripple effect and make it easier to use everywhere --- resources/qml/Avatar.qml | 15 +- resources/qml/Completer.qml | 7 +- resources/qml/ImageButton.qml | 2 - resources/qml/RoomList.qml | 5 + resources/qml/components/TextButton.qml | 2 - resources/qml/ui/Ripple.qml | 238 ++++++++++-------------- 6 files changed, 106 insertions(+), 163 deletions(-) diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml index edde1556..aca4a1a7 100644 --- a/resources/qml/Avatar.qml +++ b/resources/qml/Avatar.qml @@ -47,17 +47,6 @@ Rectangle { anchors.fill: parent visible: Settings.useIdenticon && img.status != Image.Ready source: Settings.useIdenticon ? ("image://jdenticon/" + (userid !== "" ? userid : roomid) + "?radius=" + (Settings.avatarCircles ? 100 : 25)) : "" - - MouseArea { - anchors.fill: parent - - Ripple { - rippleTarget: parent - color: Qt.rgba(Nheko.colors.alternateBase.r, Nheko.colors.alternateBase.g, Nheko.colors.alternateBase.b, 0.5) - } - - } - } Image { @@ -118,4 +107,8 @@ Rectangle { onSingleTapped: avatar.clicked(eventPoint) } + Ripple { + color: Qt.rgba(Nheko.colors.alternateBase.r, Nheko.colors.alternateBase.g, Nheko.colors.alternateBase.b, 0.5) + } + } diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index b10b906e..df327e49 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -129,10 +129,9 @@ Popup { if (popup.completerName == "room") popup.completionSelected(model.roomid); } - Ripple { - rippleTarget: mouseArea - color: Qt.rgba(Nheko.colors.base.r, Nheko.colors.base.g, Nheko.colors.base.b, 0.5) - } + } + Ripple { + color: Qt.rgba(Nheko.colors.base.r, Nheko.colors.base.g, Nheko.colors.base.b, 0.5) } DelegateChooser { diff --git a/resources/qml/ImageButton.qml b/resources/qml/ImageButton.qml index 7779c530..c68b6cde 100644 --- a/resources/qml/ImageButton.qml +++ b/resources/qml/ImageButton.qml @@ -39,8 +39,6 @@ AbstractButton { Ripple { color: Qt.rgba(buttonTextColor.r, buttonTextColor.g, buttonTextColor.b, 0.5) - clip: false - rippleTarget: button } } diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index eb511563..2f8a2d43 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -4,6 +4,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later import "./dialogs" +import "./ui" import Qt.labs.platform 1.1 as Platform import QtQml 2.12 import QtQuick 2.15 @@ -137,6 +138,10 @@ Page { required property bool isDirect required property string directChatOtherUserId + Ripple { + color: Qt.rgba(Nheko.colors.dark.r, Nheko.colors.dark.g, Nheko.colors.dark.b, 0.5) + } + height: avatarSize + 2 * Nheko.paddingMedium width: ListView.view.width state: "normal" diff --git a/resources/qml/components/TextButton.qml b/resources/qml/components/TextButton.qml index 09f1e6fd..a37f3aee 100644 --- a/resources/qml/components/TextButton.qml +++ b/resources/qml/components/TextButton.qml @@ -42,8 +42,6 @@ AbstractButton { Ripple { color: Qt.rgba(buttonTextColor.r, buttonTextColor.g, buttonTextColor.b, 0.5) - clip: false - rippleTarget: button } } diff --git a/resources/qml/ui/Ripple.qml b/resources/qml/ui/Ripple.qml index ac06d27a..786aa351 100644 --- a/resources/qml/ui/Ripple.qml +++ b/resources/qml/ui/Ripple.qml @@ -4,179 +4,129 @@ // SPDX-License-Identifier: GPL-3.0-or-later import QtGraphicalEffects 1.0 -import QtQuick 2.10 -import QtQuick.Controls 2.3 +import QtQuick 2.15 +import QtQuick.Controls 2.15 Item { id: ripple - property alias clip: backgroundLayer.clip - property real radius: 0 property color color: "#22000000" property real maxRadius: Math.max(width, height) readonly property real radiusAnimationRate: 0.05 readonly property real radiusTailAnimationRate: 0.5 readonly property real opacityAnimationDuration: 300 - readonly property real diameter: radius * 2 - property real centerX - property real centerY property var rippleTarget: parent - function start() { - console.log("Starting ripple animation"); - ripple.state = "ACTIVE"; - } - - function stop() { - console.log("Stopping ripple animation"); - ripple.state = "NORMAL"; - } - anchors.fill: parent - state: "NORMAL" - states: [ - State { - name: "NORMAL" - }, - State { - name: "ACTIVE" + + PointHandler { + id: ph + + onGrabChanged: { + circle.centerX = point.position.x + circle.centerY = point.position.y } - ] - transitions: [ - Transition { - from: "NORMAL" - to: "ACTIVE" - SequentialAnimation { - ScriptAction { - script: { - ripple.opacity = 1; - ripple.visible = true; + target: Rectangle { + id: backgroundLayer + parent: rippleTarget + + anchors.fill: parent + color: "transparent" + clip: true + + Rectangle { + id: circle + + property real centerX + property real centerY + + x: centerX - radius + y: centerY - radius + + height: radius*2 + width: radius*2 + radius: 0 + color: ripple.color + + state: ph.active ? "ACTIVE" : "NORMAL" + states: [ + State { + name: "NORMAL" + }, + State { + name: "ACTIVE" } - } + ] + transitions: [ + Transition { + from: "NORMAL" + to: "ACTIVE" - NumberAnimation { - id: radius_animation + SequentialAnimation { + //PropertyAction { target: circle; property: "centerX"; value: ph.point.position.x } + //PropertyAction { target: circle; property: "centerY"; value: ph.point.position.y } + PropertyAction { target: circle; property: "visible"; value: true } + PropertyAction { target: circle; property: "opacity"; value: 1 } - target: ripple - properties: "radius" - from: 0 - to: ripple.maxRadius - duration: ripple.maxRadius / ripple.radiusAnimationRate + NumberAnimation { + id: radius_animation - easing { - type: Easing.OutQuad - } + target: circle + properties: "radius" + from: 0 + to: ripple.maxRadius + duration: ripple.maxRadius / ripple.radiusAnimationRate - } + easing { + type: Easing.OutQuad + } - } + } - }, - Transition { - from: "ACTIVE" - to: "NORMAL" - - SequentialAnimation { - ParallelAnimation { - NumberAnimation { - id: radius_tail_animation - - target: ripple - properties: "radius" - to: ripple.maxRadius - duration: ripple.maxRadius / ripple.radiusTailAnimationRate - - easing { - type: Easing.Linear } - } + }, + Transition { + from: "ACTIVE" + to: "NORMAL" - NumberAnimation { - id: opacity_animation + SequentialAnimation { + ParallelAnimation { + NumberAnimation { + id: radius_tail_animation - target: ripple - properties: "opacity" - to: 0 - duration: ripple.opacityAnimationDuration + target: circle + properties: "radius" + to: ripple.maxRadius + duration: ripple.maxRadius / ripple.radiusTailAnimationRate - easing { - type: Easing.InQuad + easing { + type: Easing.Linear + } + + } + + NumberAnimation { + id: opacity_animation + + target: ripple + properties: "opacity" + to: 0 + duration: ripple.opacityAnimationDuration + + easing { + type: Easing.InQuad + } + + } + + } + PropertyAction { target: circle; property: "visible"; value: false } } - } - - } - - ScriptAction { - script: { - ripple.visible = false; - } - } - + ] } - } - ] - - Connections { - // Button - // Default to center - - function onPressed(mouse) { - // MouseArea - if (mouse) { - ripple.centerX = mouse.x; - ripple.centerY = mouse.y; - } else if (rippleTarget.pressX) { - ripple.centerX = rippleTarget.pressX; - ripple.centerY = rippleTarget.pressY; - } else { - ripple.centerX = width / 2; - ripple.centerY = height / 2; - } - ripple.start(); - } - - function onReleased() { - ripple.stop(); - } - - function onExited() { - ripple.stop(); - } - - function onCanceled() { - ripple.stop(); - } - - function onClicked() { - ripple.stop(); - } - - target: rippleTarget - ignoreUnknownSignals: true } - - Rectangle { - id: backgroundLayer - - anchors.fill: parent - color: "transparent" - clip: true - - Rectangle { - id: circle - - x: ripple.centerX - ripple.radius - y: ripple.centerY - ripple.radius - height: ripple.diameter - width: ripple.diameter - radius: ripple.radius - color: ripple.color - } - - } - }