This commit is contained in:
Karthik Nishanth 2024-11-19 16:31:53 -08:00 committed by GitHub
commit 47c48d997b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 200 additions and 137 deletions

View file

@ -805,6 +805,7 @@ set(QML_SOURCES
resources/qml/pages/WelcomePage.qml resources/qml/pages/WelcomePage.qml
resources/qml/ui/NhekoSlider.qml resources/qml/ui/NhekoSlider.qml
resources/qml/ui/Ripple.qml resources/qml/ui/Ripple.qml
resources/qml/ui/RippleImpl.qml
resources/qml/ui/Snackbar.qml resources/qml/ui/Snackbar.qml
resources/qml/ui/Spinner.qml resources/qml/ui/Spinner.qml
resources/qml/ui/animations/BlinkAnimation.qml resources/qml/ui/animations/BlinkAnimation.qml

View file

@ -79,6 +79,7 @@ ColumnLayout {
from: "" from: ""
reversible: true reversible: true
to: "focused" to: "focused"
enabled: !Settings.reducedMotion
NumberAnimation { NumberAnimation {
alwaysRunToEnd: true alwaysRunToEnd: true
@ -164,6 +165,7 @@ ColumnLayout {
from: "" from: ""
reversible: true reversible: true
to: "focused" to: "focused"
enabled: !Settings.reducedMotion
NumberAnimation { NumberAnimation {
alwaysRunToEnd: true alwaysRunToEnd: true

View file

@ -335,6 +335,7 @@ Rectangle {
y: messageInput.positionToRectangle(messageInput.completerTriggeredAt).y - height y: messageInput.positionToRectangle(messageInput.completerTriggeredAt).y - height
enter: Transition { enter: Transition {
enabled: !Settings.reducedMotion
NumberAnimation { NumberAnimation {
duration: 100 duration: 100
from: 0 from: 0
@ -343,6 +344,7 @@ Rectangle {
} }
} }
exit: Transition { exit: Transition {
enabled: !Settings.reducedMotion
NumberAnimation { NumberAnimation {
duration: 100 duration: 100
from: 1 from: 1

View file

@ -686,6 +686,7 @@ Item {
from: "" from: ""
reversible: true reversible: true
to: "shown" to: "shown"
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
PauseAnimation { PauseAnimation {

View file

@ -68,6 +68,7 @@ Item {
from: "Invisible" from: "Invisible"
reversible: true reversible: true
to: "Visible" to: "Visible"
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
NumberAnimation { NumberAnimation {

View file

@ -430,6 +430,7 @@ Pane {
Transition { Transition {
id: reducedMotionTransitionExit id: reducedMotionTransitionExit
enabled: !Settings.reducedMotion
PropertyAnimation { PropertyAnimation {
duration: 200 duration: 200
@ -440,6 +441,7 @@ Pane {
} }
Transition { Transition {
id: reducedMotionTransitionEnter id: reducedMotionTransitionEnter
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
PropertyAction { PropertyAction {

View file

@ -107,6 +107,7 @@ TimelineEvent {
transitions: Transition { transitions: Transition {
from: "" from: ""
to: "revealed" to: "revealed"
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
PropertyAnimation { PropertyAnimation {

View file

@ -107,6 +107,7 @@ TimelineEvent {
transitions: Transition { transitions: Transition {
from: "" from: ""
to: "revealed" to: "revealed"
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
PropertyAnimation { PropertyAnimation {

View file

@ -5,6 +5,7 @@
import QtQuick 2.5 import QtQuick 2.5
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 2.12 import QtQuick.Controls 2.12
import im.nheko 1.0
Switch { Switch {
id: toggleButton id: toggleButton
@ -66,6 +67,7 @@ Switch {
Transition { Transition {
reversible: true reversible: true
to: "off" to: "off"
enabled: !Settings.reducedMotion
ParallelAnimation { ParallelAnimation {
NumberAnimation { NumberAnimation {

View file

@ -74,6 +74,7 @@ AbstractButton {
from: "ImageVisible" from: "ImageVisible"
to: "BlurhashVisible" to: "BlurhashVisible"
reversible: true reversible: true
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
PropertyAction { PropertyAction {

View file

@ -2,128 +2,18 @@
// //
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick import QtQuick 2.15
import im.nheko 1.0
Item { Item {
id: ripple id: wrapper
property color color
property color color: "#22000000" Loader {
property real maxRadius: Math.max(width, height) Component {
readonly property real radiusAnimationRate: 0.05 id: ripple
readonly property real radiusTailAnimationRate: 0.5 RippleImpl { color: color; parent: wrapper.parent; }
readonly property real opacityAnimationDuration: 300
property var rippleTarget: parent
anchors.fill: parent
PointHandler {
id: ph
onGrabChanged: (_, point) => {
circle.centerX = point.position.x
circle.centerY = point.position.y
}
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"
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 }
NumberAnimation {
id: radius_animation
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: circle
properties: "radius"
to: ripple.maxRadius
duration: ripple.maxRadius / ripple.radiusTailAnimationRate
easing {
type: Easing.Linear
}
}
NumberAnimation {
id: opacity_animation
target: circle
properties: "opacity"
to: 0
duration: ripple.opacityAnimationDuration
easing {
type: Easing.InQuad
}
}
}
PropertyAction { target: circle; property: "visible"; value: false }
}
}
]
}
} }
sourceComponent: !Settings.reducedMotion ? ripple : undefined
} }
} }

View file

@ -0,0 +1,131 @@
// SPDX-FileCopyrightText: Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.15
Item {
id: ripple
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
property var rippleTarget: parent
anchors.fill: parent
PointHandler {
id: ph
onGrabChanged: (_, point) => {
circle.centerX = point.position.x
circle.centerY = point.position.y
}
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"
enabled: !Settings.reducedMotion
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 }
NumberAnimation {
id: radius_animation
target: circle
properties: "radius"
from: 0
to: ripple.maxRadius
duration: ripple.maxRadius / ripple.radiusAnimationRate
easing {
type: Easing.OutQuad
}
}
}
},
Transition {
from: "ACTIVE"
to: "NORMAL"
enabled: !Settings.reducedMotion
SequentialAnimation {
ParallelAnimation {
NumberAnimation {
id: radius_tail_animation
target: circle
properties: "radius"
to: ripple.maxRadius
duration: ripple.maxRadius / ripple.radiusTailAnimationRate
easing {
type: Easing.Linear
}
}
NumberAnimation {
id: opacity_animation
target: circle
properties: "opacity"
to: 0
duration: ripple.opacityAnimationDuration
easing {
type: Easing.InQuad
}
}
}
PropertyAction { target: circle; property: "visible"; value: false }
}
}
]
}
}
}
}

View file

@ -61,6 +61,7 @@ Popup {
} }
enter: Transition { enter: Transition {
enabled: !Settings.reducedMotion
NumberAnimation { NumberAnimation {
target: snackbar target: snackbar
property: "opacity" property: "opacity"
@ -79,6 +80,7 @@ Popup {
} }
} }
exit: Transition { exit: Transition {
enabled: !Settings.reducedMotion
NumberAnimation { NumberAnimation {
target: snackbar target: snackbar
property: "opacity" property: "opacity"

View file

@ -146,6 +146,7 @@ Rectangle {
Transition { Transition {
from: "" from: ""
to: "shown" to: "shown"
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
PauseAnimation { PauseAnimation {
@ -163,6 +164,7 @@ Rectangle {
Transition { Transition {
from: "shown" from: "shown"
to: "" to: ""
enabled: !Settings.reducedMotion
SequentialAnimation { SequentialAnimation {
PauseAnimation { PauseAnimation {

View file

@ -55,21 +55,21 @@ Nheko::inactiveColors() const
auto theme = UserSettings::instance()->theme(); auto theme = UserSettings::instance()->theme();
if (theme == QLatin1String("light")) { if (theme == QLatin1String("light")) {
static QPalette lightInactive = [] { static QPalette lightInactive = [] {
auto lightInactive = Theme::paletteFromTheme(u"light"); auto lightInactive = Theme::paletteFromTheme(Theme::Kind::Light);
lightInactive.setCurrentColorGroup(QPalette::ColorGroup::Inactive); lightInactive.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
return lightInactive; return lightInactive;
}(); }();
return lightInactive; return lightInactive;
} else if (theme == QLatin1String("dark")) { } else if (theme == QLatin1String("dark")) {
static QPalette darkInactive = [] { static QPalette darkInactive = [] {
auto darkInactive = Theme::paletteFromTheme(u"dark"); auto darkInactive = Theme::paletteFromTheme(Theme::Kind::Dark);
darkInactive.setCurrentColorGroup(QPalette::ColorGroup::Inactive); darkInactive.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
return darkInactive; return darkInactive;
}(); }();
return darkInactive; return darkInactive;
} else { } else {
static QPalette originalInactive = [] { static QPalette originalInactive = [] {
auto originalInactive = Theme::paletteFromTheme(u"system"); auto originalInactive = Theme::paletteFromTheme(Theme::Kind::System);
originalInactive.setCurrentColorGroup(QPalette::ColorGroup::Inactive); originalInactive.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
return originalInactive; return originalInactive;
}(); }();
@ -80,7 +80,7 @@ Nheko::inactiveColors() const
Theme Theme
Nheko::theme() const Nheko::theme() const
{ {
return Theme(UserSettings::instance()->theme()); return Theme(Theme::kindFromString(UserSettings::instance()->theme()));
} }
int int

View file

@ -5,10 +5,10 @@
#include "Theme.h" #include "Theme.h"
QPalette QPalette
Theme::paletteFromTheme(QStringView theme) Theme::paletteFromTheme(Theme::Kind theme)
{ {
static QPalette original; static QPalette original;
if (theme == u"light") { if (theme == Kind::Light) {
static QPalette lightActive = [] { static QPalette lightActive = [] {
QPalette lightActive( QPalette lightActive(
/*windowText*/ QColor(0x33, 0x33, 0x33), /*windowText*/ QColor(0x33, 0x33, 0x33),
@ -30,7 +30,7 @@ Theme::paletteFromTheme(QStringView theme)
return lightActive; return lightActive;
}(); }();
return lightActive; return lightActive;
} else if (theme == u"dark") { } else if (theme == Kind::Dark) {
static QPalette darkActive = [] { static QPalette darkActive = [] {
QPalette darkActive( QPalette darkActive(
/*windowText*/ QColor(0xca, 0xcc, 0xd1), /*windowText*/ QColor(0xca, 0xcc, 0xd1),
@ -57,27 +57,30 @@ Theme::paletteFromTheme(QStringView theme)
} }
} }
Theme::Theme(QStringView theme) QPalette
Theme::paletteFromTheme(QStringView theme)
{
return paletteFromTheme(kindFromString(theme));
}
Theme::Theme(Theme::Kind theme)
{ {
auto p = paletteFromTheme(theme); auto p = paletteFromTheme(theme);
separator_ = p.mid().color(); separator_ = p.mid().color();
if (theme == u"light") { if (theme == Kind::Light) {
sidebarBackground_ = QColor(0x23, 0x36, 0x49); sidebarBackground_ = QColor(0x23, 0x36, 0x49);
alternateButton_ = QColor(0xcc, 0xcc, 0xcc);
red_ = QColor(0xa8, 0x23, 0x53); red_ = QColor(0xa8, 0x23, 0x53);
green_ = QColor(QColorConstants::Svg::green); green_ = QColor(QColorConstants::Svg::green);
orange_ = QColor(0xfc, 0xbe, 0x05); orange_ = QColor(0xfc, 0xbe, 0x05);
error_ = QColor(0xdd, 0x3d, 0x3d); error_ = QColor(0xdd, 0x3d, 0x3d);
} else if (theme == u"dark") { } else if (theme == Kind::Dark) {
sidebarBackground_ = QColor(0x2d, 0x31, 0x39); sidebarBackground_ = QColor(0x2d, 0x31, 0x39);
alternateButton_ = QColor(0x41, 0x4A, 0x59);
red_ = QColor(0xa8, 0x23, 0x53); red_ = QColor(0xa8, 0x23, 0x53);
green_ = QColor(QColorConstants::Svg::green); green_ = QColor(QColorConstants::Svg::green);
orange_ = QColor(0xfc, 0xc5, 0x3a); orange_ = QColor(0xfc, 0xc5, 0x3a);
error_ = QColor(0xdd, 0x3d, 0x3d); error_ = QColor(0xdd, 0x3d, 0x3d);
} else { } else {
sidebarBackground_ = p.window().color(); sidebarBackground_ = p.window().color();
alternateButton_ = p.dark().color();
red_ = QColor(QColorConstants::Svg::red); red_ = QColor(QColorConstants::Svg::red);
green_ = QColor(QColorConstants::Svg::green); green_ = QColor(QColorConstants::Svg::green);
orange_ = QColor(QColorConstants::Svg::orange); // SVG orange orange_ = QColor(QColorConstants::Svg::orange); // SVG orange
@ -85,4 +88,18 @@ Theme::Theme(QStringView theme)
} }
} }
Theme::Kind
Theme::kindFromString(QStringView kind)
{
if (kind == u"light") {
return Kind::Light;
} else if (kind == u"dark") {
return Kind::Dark;
} else if (kind == u"system") {
return Kind::System;
} else {
throw std::invalid_argument("Unknown theme kind: " + kind.toString().toStdString());
}
}
#include "moc_Theme.cpp" #include "moc_Theme.cpp"

View file

@ -14,7 +14,6 @@ class Theme final : public QPalette
QML_ANONYMOUS QML_ANONYMOUS
Q_PROPERTY(QColor sidebarBackground READ sidebarBackground CONSTANT) Q_PROPERTY(QColor sidebarBackground READ sidebarBackground CONSTANT)
Q_PROPERTY(QColor alternateButton READ alternateButton CONSTANT)
Q_PROPERTY(QColor separator READ separator CONSTANT) Q_PROPERTY(QColor separator READ separator CONSTANT)
Q_PROPERTY(QColor red READ red CONSTANT) Q_PROPERTY(QColor red READ red CONSTANT)
Q_PROPERTY(QColor green READ green CONSTANT) Q_PROPERTY(QColor green READ green CONSTANT)
@ -23,12 +22,20 @@ class Theme final : public QPalette
Q_PROPERTY(QColor online READ online CONSTANT) Q_PROPERTY(QColor online READ online CONSTANT)
Q_PROPERTY(QColor unavailable READ unavailable CONSTANT) Q_PROPERTY(QColor unavailable READ unavailable CONSTANT)
public: public:
Theme() {} enum class Kind {
explicit Theme(QStringView theme); Light,
Dark,
System,
};
static Kind kindFromString(QStringView kind);
static QPalette paletteFromTheme(Kind theme);
static QPalette paletteFromTheme(QStringView theme); static QPalette paletteFromTheme(QStringView theme);
Theme() {}
explicit Theme(Kind theme);
QColor sidebarBackground() const { return sidebarBackground_; } QColor sidebarBackground() const { return sidebarBackground_; }
QColor alternateButton() const { return alternateButton_; }
QColor separator() const { return separator_; } QColor separator() const { return separator_; }
QColor red() const { return red_; } QColor red() const { return red_; }
QColor green() const { return green_; } QColor green() const { return green_; }
@ -38,5 +45,5 @@ public:
QColor unavailable() const { return QColor(0xff, 0x99, 0x33); } QColor unavailable() const { return QColor(0xff, 0x99, 0x33); }
private: private:
QColor sidebarBackground_, separator_, red_, green_, error_, orange_, alternateButton_; QColor sidebarBackground_, separator_, red_, green_, error_, orange_;
}; };