feat: 'Prefer reduced motion' setting (accessibility / animation opt-out)

Config::reducedMotion (default false = playful animations ON). Surfaced as a
checkbox on first run (wizard PageMenu) and in Settings → Appearance —
unchecked by default, matching the OS 'Reduce Motion' convention. The mining
tab's AnimatedImages now freeze when it's set (MiningBackend exposes it to
mining.qml). Foundation for gating the ambient silliness to come.
This commit is contained in:
jwinterm
2026-08-30 12:36:15 -04:00
parent 0ed8c005c5
commit 7b71f5dc9a
9 changed files with 41 additions and 0 deletions
+6
View File
@@ -139,6 +139,12 @@ void Settings::setupAppearanceTab() {
emit updateBalance();
});
// [Prefer reduced motion] wowlet: gate playful animations (mining tab, loaders, ...)
ui->checkBox_reducedMotion->setChecked(conf()->get(Config::reducedMotion).toBool());
connect(ui->checkBox_reducedMotion, &QCheckBox::toggled, [this](bool toggled){
conf()->set(Config::reducedMotion, toggled);
});
// [Preferred fiat currency]
QStringList availableFiatCurrencies = appData()->prices.rates.keys();
for (const auto &currency : availableFiatCurrencies) {
+7
View File
@@ -159,6 +159,13 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="checkBox_reducedMotion">
<property name="text">
<string>Prefer reduced motion (disable playful animations)</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
+4
View File
@@ -35,6 +35,7 @@ Rectangle {
}
AnimatedImage {
playing: !mining.reducedMotion // wowlet: respect reduced-motion
//visible: mining.daemonMiningState === 0
source: "qrc:/mining/bg1.gif"
fillMode: Image.PreserveAspectCrop
@@ -195,6 +196,7 @@ Rectangle {
}
AnimatedImage {
playing: !mining.reducedMotion // wowlet: respect reduced-motion
visible: mining.daemonMiningState !== 0
source: "qrc:/mining/mining.webp"
fillMode: Image.PreserveAspectCrop
@@ -436,6 +438,7 @@ Rectangle {
smooth: false
AnimatedImage {
playing: !mining.reducedMotion // wowlet: respect reduced-motion
source: mining.daemonMiningState === 0 ? "qrc:/assets/images/dog_sitting.gif" : "qrc:/assets/images/dog_running.gif"
width: 80
height: 60
@@ -546,6 +549,7 @@ Rectangle {
}
AnimatedImage {
playing: !mining.reducedMotion // wowlet: respect reduced-motion
visible: mining.daemonMiningState !== 0
source: "qrc:/mining/elmo.gif"
width: 106
+1
View File
@@ -30,6 +30,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::homeWidget,{QS("homeWidget"), "ccs"}},
{Config::donateBeg,{QS("donateBeg"), 1}},
{Config::showHistorySyncNotice, {QS("showHistorySyncNotice"), true}},
{Config::reducedMotion, {QS("reducedMotion"), false}},
{Config::geometry, {QS("geometry"), {}}},
{Config::windowState, {QS("windowState"), {}}},
+1
View File
@@ -29,6 +29,7 @@ public:
homeWidget,
donateBeg,
showHistorySyncNotice,
reducedMotion, // wowlet: disable playful animations (accessibility / preference)
geometry,
windowState,
+3
View File
@@ -11,6 +11,8 @@
#include <QThread>
#include <QDateTime>
#include "utils/config.h"
static QString formatUptime(qint64 secs) {
return QString("%1:%2:%3")
.arg(secs / 3600, 2, 10, QChar('0'))
@@ -29,6 +31,7 @@ MiningWidget::MiningWidget(Wallet *wallet, QWidget *parent)
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_quickWidget);
m_backend->setReducedMotion(conf()->get(Config::reducedMotion).toBool());
m_quickWidget->rootContext()->setContextProperty("mining", m_backend);
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_quickWidget->setSource(QUrl("qrc:/qml/mining.qml"));
+5
View File
@@ -15,13 +15,17 @@
class MiningBackend : public QObject {
Q_OBJECT
Q_PROPERTY(int daemonMiningState READ daemonMiningState NOTIFY daemonMiningStateChanged)
Q_PROPERTY(bool reducedMotion READ reducedMotion NOTIFY reducedMotionChanged)
public:
explicit MiningBackend(QObject *parent = nullptr) : QObject(parent) {}
int daemonMiningState() const { return m_state; }
void setState(int s) { if (m_state != s) { m_state = s; emit daemonMiningStateChanged(); } }
bool reducedMotion() const { return m_reducedMotion; }
void setReducedMotion(bool r) { if (m_reducedMotion != r) { m_reducedMotion = r; emit reducedMotionChanged(); } }
signals:
void daemonMiningStateChanged();
void reducedMotionChanged();
void daemonOutput(const QString &line);
void syncStatus(int from, int to, int pct);
void uptimeChanged(const QString &uptime);
@@ -29,6 +33,7 @@ signals:
private:
int m_state = 0; // 0:idle 1:startup 2:syncing 3:mining
bool m_reducedMotion = false;
};
// wowlet: the pixel-art mining tab. Hosts mining.qml and wires its pick-axe to the wallet's solo
+7
View File
@@ -27,6 +27,13 @@ PageMenu::PageMenu(WizardFields *fields, WalletKeysFilesModel *wallets, QWidget
});
QString settingsSkin = conf()->get(Config::skin).toString();
// wowlet: reduced-motion opt-out, surfaced on first run (unchecked = playful
// animations on, the default). Also lives in Settings → Appearance.
ui->checkBox_reducedMotion->setChecked(conf()->get(Config::reducedMotion).toBool());
connect(ui->checkBox_reducedMotion, &QCheckBox::toggled, [](bool toggled){
conf()->set(Config::reducedMotion, toggled);
});
}
void PageMenu::initializePage() {
+7
View File
@@ -192,6 +192,13 @@
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_reducedMotion">
<property name="text">
<string>Prefer reduced motion (disable playful animations)</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>