wowlet: first-run 'be your own node' welcome + deferred startup + non-blocking node toggle. On first launch a welcome dialog lets the user choose own-node vs remote BEFORE any node starts (gated on firstRun; later launches use the saved choice); node start moved past it in WindowManager. Settings toggle now stops wownerod non-blocking (no UI freeze while it flushes LMDB). Copy: 'many recommended', no em-dash

This commit is contained in:
jwinterm
2026-06-19 16:02:17 -04:00
parent 487875ee9e
commit 3eab1e14fa
6 changed files with 66 additions and 12 deletions
+1 -1
View File
@@ -176,7 +176,7 @@ void Settings::setupNetworkTab() {
if (enabled)
daemonManager()->start();
else
daemonManager()->stop();
daemonManager()->stop(false); // non-blocking: don't freeze Settings while wownerod flushes
m_nodes->autoConnect(true);
});
} else {
+56 -5
View File
@@ -3,9 +3,15 @@
#include "WindowManager.h"
#include <QCheckBox>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFont>
#include <QInputDialog>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWindow>
#include "Application.h"
@@ -48,16 +54,22 @@ WindowManager::WindowManager(QObject *parent)
this->buildTrayMenu();
m_tray->setVisible(conf()->get(Config::showTrayIcon).toBool());
// wowlet: boot the embedded wownerod node early so it syncs while the user opens their wallet.
// No-op if the user disabled the local node (Config::runLocalNode) or no daemon is bundled.
daemonManager()->init();
daemonManager()->start();
this->initSkins();
this->patchMacStylesheet();
this->showCrashLogs();
// wowlet: on the very first launch, let the user choose their own node vs a remote one BEFORE anything
// connects. No node — local or remote — starts until they hit Continue. Later launches use the saved choice.
if (conf()->get(Config::firstRun).toBool()) {
this->showNodeWelcome();
}
// wowlet: boot the embedded wownerod (shouldStartDaemon() makes this a no-op if the user chose a remote
// node), so it syncs while the user opens their wallet.
daemonManager()->init();
daemonManager()->start();
// wowlet: the embedded local node is configured automatically — skip the first-run network wizard.
this->onInitialNetworkConfigured();
@@ -68,6 +80,45 @@ WindowManager::WindowManager(QObject *parent)
}
}
// wowlet: first-run "be your own node" welcome. Shown before any node starts; records the user's choice
// in Config::runLocalNode, which start()/autoConnect then honour.
void WindowManager::showNodeWelcome() {
QDialog dlg;
dlg.setWindowTitle("Welcome to wowlet");
dlg.setMinimumWidth(440);
auto *title = new QLabel("🐕 Welcome to wowlet", &dlg);
QFont tf = title->font();
tf.setPointSize(tf.pointSize() + 4);
tf.setBold(true);
title->setFont(tf);
auto *intro = new QLabel("wowlet runs your own Wownero node by default: be your own boss and help run the network.", &dlg);
intro->setWordWrap(true);
auto *check = new QCheckBox("Run your own Wownero node (many recommended)", &dlg);
check->setChecked(conf()->get(Config::runLocalNode).toBool());
auto *hint = new QLabel("(untick to use a remote node instead)", &dlg);
hint->setStyleSheet("color: gray;");
auto *btn = new QPushButton("Continue", &dlg);
btn->setDefault(true);
connect(btn, &QPushButton::clicked, &dlg, &QDialog::accept);
auto *layout = new QVBoxLayout(&dlg);
layout->addWidget(title);
layout->addWidget(intro);
layout->addSpacing(8);
layout->addWidget(check);
layout->addWidget(hint);
layout->addSpacing(8);
layout->addWidget(btn, 0, Qt::AlignRight);
dlg.exec(); // modal — blocks until Continue
conf()->set(Config::runLocalNode, check->isChecked());
}
QPointer<WindowManager> WindowManager::m_instance(nullptr);
void WindowManager::setEventFilter(EventFilter *ef) {
+1
View File
@@ -80,6 +80,7 @@ private:
bool autoOpenWallet();
void initWizard();
void showNodeWelcome(); // wowlet: first-run "be your own node" choice, before any node starts
WalletWizard* createWizard(WalletWizard::Page startPage);
void handleWalletError(const Utils::Message &message);
+4 -2
View File
@@ -97,7 +97,7 @@ void DaemonManager::start() {
m_started = true;
}
void DaemonManager::stop() {
void DaemonManager::stop(bool wait) {
m_stopping = true;
if (m_process->state() == QProcess::ProcessState::NotRunning) {
m_started = false;
@@ -107,12 +107,14 @@ void DaemonManager::stop() {
// wownerod owns an LMDB database. Send SIGTERM so it flushes and exits cleanly; only hard-kill
// if it refuses to shut down, to avoid blockchain database corruption.
m_process->terminate();
m_started = false;
if (!wait)
return; // toggle/live use: let it flush + exit in the background instead of freezing the UI thread.
if (!m_process->waitForFinished(30000)) {
qWarning() << "wownerod did not exit gracefully within 30s; killing";
m_process->kill();
m_process->waitForFinished(5000);
}
m_started = false;
}
void DaemonManager::onStateChanged(QProcess::ProcessState state) {
+1 -1
View File
@@ -26,7 +26,7 @@ public:
void init();
void start();
void stop();
void stop(bool wait = true); // wait=false: non-blocking (don't freeze the UI on a settings toggle)
bool unpackBins();
bool isStarted() const { return m_started; }
+3 -3
View File
@@ -59,11 +59,11 @@ NodeWidget::NodeWidget(QWidget *parent)
// wowlet: built-in node toggle + the "why run your own node" messaging. Running your own node is
// a privacy win (no remote operator sees your wallet) AND it strengthens the Wownero network by
// adding a peer — a deliberate differentiator we surface clearly here.
m_localNodeCheck = new QCheckBox(tr("Run your own Wownero node (much recommended)"), this);
m_localNodeCheck = new QCheckBox(tr("Run your own Wownero node (many recommended)"), this);
m_localNodeCheck->setChecked(conf()->get(Config::runLocalNode).toBool());
auto *localNodeInfo = new QLabel(
tr("wowlet bundles its own node so you can be your own boss — and every node keeps the Wownero "
"network strong + decentralized. 🐕 Uncheck to use a remote node instead."), this);
tr("wowlet runs your own Wownero node by default: be your own boss and help run the network. "
"🐕 Uncheck to use a remote node instead."), this);
localNodeInfo->setWordWrap(true);
localNodeInfo->setStyleSheet("color: gray;");