From 3b5db02e0923cd17f53d4a08396d38465eb5b0b0 Mon Sep 17 00:00:00 2001 From: DanS Date: Fri, 17 Jul 2026 18:44:55 -0500 Subject: [PATCH] feat(app): font-atlas rebuild hook + clock/emoji sync - requestFontRebuild() + preFrame handling so toggling color emoji swaps the atlas live; request a rebuild at startup when the saved setting wants color. - preFrame syncs Typography's color-emoji flag and the util clock flag from settings. - Chat 0-conf fast-scan cadence now reads the user's poll-rate setting (was a hardcoded 2.5s). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app.cpp | 21 ++++++++++++++++++++- src/app.h | 4 ++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/app.cpp b/src/app.cpp index 6e985a6..04e159e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -293,6 +293,9 @@ bool App::init() if (!settings_->load()) { DEBUG_LOGF("Warning: Could not load settings, using defaults\n"); } + // The initial font atlas is built (in main, before App renders) with monochrome emoji. If the saved + // setting wants color, request a rebuild so the first preFrame switches to the FreeType color atlas. + if (settings_->getChatEmojiColor()) font_rebuild_requested_ = true; // On upgrade (version mismatch), re-save to persist new defaults + current version if (settings_->needsUpgradeSave()) { DEBUG_LOGF("[INFO] Wallet upgraded — re-saving settings with new defaults\n"); @@ -532,6 +535,21 @@ void App::preFrame() DEBUG_LOGF("App: Font atlas rebuilt after user font-scale change (%.1fx)\n", ui::Layout::userFontScale()); } + + // Keep Typography's emoji-style flag in sync with the setting so any reload (font-scale, DPI, or the + // explicit request below) picks up the right emoji font. Inert unless this is a FreeType build. + if (settings_) ui::material::Typography::instance().setColorEmoji(settings_->getChatEmojiColor()); + + // App-wide clock format (24h/12h) — drives every user-facing timestamp via util::formatClock*. + if (settings_) util::setClock12h(settings_->getTimeFormat() == 1); + + // Explicit rebuild request (e.g. the chat color-emoji toggle) — reload picks up the new emoji style. + if (font_rebuild_requested_) { + font_rebuild_requested_ = false; + auto& typo = ui::material::Typography::instance(); + typo.reload(io, typo.getDpiScale()); + DEBUG_LOGF("App: Font atlas rebuilt on request (chat emoji style)\n"); + } } namespace { @@ -1174,7 +1192,8 @@ void App::update() // normal harvest only re-scans on a new block. Self-gated (no-op without a chat identity / // connection / on lite); the in-flight guard keeps overlapping RPCs from stacking. chat_fast_scan_accum_ += ImGui::GetIO().DeltaTime; - if (chat_fast_scan_accum_ >= 2.5f) { + const float chatPoll = settings_ ? settings_->getChatPollRateSec() : 2.5f; // user-configurable + if (chat_fast_scan_accum_ >= chatPoll) { chat_fast_scan_accum_ = 0.0f; fastScanChatMemos(); } diff --git a/src/app.h b/src/app.h index 1140383..a3b463d 100644 --- a/src/app.h +++ b/src/app.h @@ -171,6 +171,9 @@ public: daemon::EmbeddedDaemon* consoleDaemon(); daemon::XmrigManager* consoleXmrig(); config::Settings* settings() { return settings_.get(); } + // Request a font-atlas rebuild before the next frame (e.g. after toggling color emoji). Handled in + // preFrame() via Typography::reload — safe to call from UI code mid-frame. + void requestFontRebuild() { font_rebuild_requested_ = true; } // Lite wallet controller (non-null only in lite builds with a linked backend). wallet::LiteWalletController* liteWallet() { return lite_wallet_.get(); } // HushChat service (identity + in-memory message store); the Chat tab reads its store. @@ -736,6 +739,7 @@ private: void fastScanChatMemos(); bool chat_fast_scan_in_flight_ = false; // guard against overlapping fast-scan RPCs float chat_fast_scan_accum_ = 0.0f; // seconds since the last fast-scan (dedicated ~2.5s poll) + bool font_rebuild_requested_ = false; // set by requestFontRebuild(); consumed in preFrame() // Lite first-run welcome prompt: dismissed for the session once the user picks an action. bool lite_firstrun_dismissed_ = false; // Lite send-time unlock: set to show the unlock modal when a spend is attempted while locked.