From 7b71f5dc9a12c75ff29648265eb4d393c93067dd Mon Sep 17 00:00:00 2001 From: jwinterm Date: Sun, 30 Aug 2026 12:36:15 -0400 Subject: [PATCH] feat: 'Prefer reduced motion' setting (accessibility / animation opt-out) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/SettingsDialog.cpp | 6 ++++++ src/SettingsDialog.ui | 7 +++++++ src/assets/qml/mining.qml | 4 ++++ src/utils/config.cpp | 1 + src/utils/config.h | 1 + src/widgets/MiningWidget.cpp | 3 +++ src/widgets/MiningWidget.h | 5 +++++ src/wizard/PageMenu.cpp | 7 +++++++ src/wizard/PageMenu.ui | 7 +++++++ 9 files changed, 41 insertions(+) diff --git a/src/SettingsDialog.cpp b/src/SettingsDialog.cpp index 0562dedf..4160525b 100644 --- a/src/SettingsDialog.cpp +++ b/src/SettingsDialog.cpp @@ -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 ¤cy : availableFiatCurrencies) { diff --git a/src/SettingsDialog.ui b/src/SettingsDialog.ui index b9ee7512..17173b65 100644 --- a/src/SettingsDialog.ui +++ b/src/SettingsDialog.ui @@ -159,6 +159,13 @@ + + + + Prefer reduced motion (disable playful animations) + + + diff --git a/src/assets/qml/mining.qml b/src/assets/qml/mining.qml index 5a659464..f75bcc30 100644 --- a/src/assets/qml/mining.qml +++ b/src/assets/qml/mining.qml @@ -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 diff --git a/src/utils/config.cpp b/src/utils/config.cpp index 36dc0589..c96b5a1e 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -30,6 +30,7 @@ static const QHash 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"), {}}}, diff --git a/src/utils/config.h b/src/utils/config.h index 0cd30b2c..b37ff383 100644 --- a/src/utils/config.h +++ b/src/utils/config.h @@ -29,6 +29,7 @@ public: homeWidget, donateBeg, showHistorySyncNotice, + reducedMotion, // wowlet: disable playful animations (accessibility / preference) geometry, windowState, diff --git a/src/widgets/MiningWidget.cpp b/src/widgets/MiningWidget.cpp index 17f6af18..8efa8340 100644 --- a/src/widgets/MiningWidget.cpp +++ b/src/widgets/MiningWidget.cpp @@ -11,6 +11,8 @@ #include #include +#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")); diff --git a/src/widgets/MiningWidget.h b/src/widgets/MiningWidget.h index 6c90141b..6707019e 100644 --- a/src/widgets/MiningWidget.h +++ b/src/widgets/MiningWidget.h @@ -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 diff --git a/src/wizard/PageMenu.cpp b/src/wizard/PageMenu.cpp index 2591ee82..c8333992 100644 --- a/src/wizard/PageMenu.cpp +++ b/src/wizard/PageMenu.cpp @@ -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() { diff --git a/src/wizard/PageMenu.ui b/src/wizard/PageMenu.ui index 77c4ee62..a7f993d2 100644 --- a/src/wizard/PageMenu.ui +++ b/src/wizard/PageMenu.ui @@ -192,6 +192,13 @@ + + + + Prefer reduced motion (disable playful animations) + + +