Skip to content

fix: repaint UI only when needed#344

Merged
QuantumExplorer merged 19 commits into
v0.9-devfrom
fix/repaint-50ms
Jun 26, 2025
Merged

fix: repaint UI only when needed#344
QuantumExplorer merged 19 commits into
v0.9-devfrom
fix/repaint-50ms

Conversation

@lklimek
Copy link
Copy Markdown
Contributor

@lklimek lklimek commented Jun 10, 2025

Current implementation forces repaint of UI every 50 ms.
This has some drawbacks, like:

  • breaks debugging sessions
  • makes testing harder as repaints are looped

This PR changes this behavior by:

  • requesting repaint only when some event happens, using wrapper around MPSC sender channels,
  • repaint executed by animated elements of UI changed to 100 ms,
  • introducing flag that allows disabling repaint caused by animated elements of the UI,
  • enabling developer mode disables animated elements.

It also refactors the code a bit to move majority of code to a library and allow easier testing.

This PR introduces basic test using egui kittest.

@lklimek lklimek requested review from QuantumExplorer and Copilot and removed request for Copilot June 10, 2025 11:40
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 10, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This update introduces a new egui-aware asynchronous message passing system, replacing previous Tokio and standard mpsc senders throughout the backend and UI layers. It adds a bundled font loader, refines developer mode and animation toggling, and modularizes the application startup process. Numerous enums are made public, and several UI components are streamlined or removed. Automated tests using egui_kittest are introduced.

Changes

File(s) Change Summary
Cargo.toml Added egui_kittest as a dev-dependency with eframe feature.
src/lib.rs New library root: declares 15 public modules for app structure.
src/utils/egui_mpsc.rs, src/utils/mod.rs Introduced egui_mpsc module with SenderAsync, SenderSync, and traits for egui repaint integration; registered in utils.
src/app.rs, src/context.rs, src/main.rs, src/bundled.rs Integrated egui-aware channels, font loading, animation toggling, modularized startup, and encapsulated developer mode.
src/backend_task/* (all submodules) Replaced tokio::sync::mpsc::Sender with egui_mpsc::SenderAsync in all backend task signatures; made many enums public.
src/components/core_zmq_listener.rs Replaced sync mpsc sender with SenderSync for ZMQ listener.
src/ui/components/styled.rs Restricted visibility of most UI components, removed several (e.g., StyledTextInput, HeroSection), updated GradientButton to use AppContext for animation.
src/ui/components/entropy_grid.rs Added Default implementation for U256EntropyGrid.
src/ui/components/left_panel.rs, src/ui/components/top_panel.rs Replaced direct atomic dev mode checks with method calls; animation repaint now routed via AppContext.
src/ui/helpers.rs, src/ui/identities/, src/ui/network_chooser_screen.rs, src/ui/tokens/ Replaced all direct atomic developer_mode field accesses with is_developer_mode() method calls.
tests/kittest/main.rs, tests/kittest/startup.rs Added new test module and a smoke test for egui app startup using egui_kittest.

Sequence Diagram(s)

sequenceDiagram
    participant UI
    participant AppContext
    participant BackendTask
    participant SenderAsync
    participant eguiCtx

    UI->>AppContext: Trigger backend task
    AppContext->>SenderAsync: Send TaskResult
    SenderAsync->>eguiCtx: request_repaint()
    SenderAsync->>UI: (TaskResult delivered via receiver)
Loading
sequenceDiagram
    participant Main
    participant AppState
    participant eguiCtx
    participant Fonts

    Main->>AppState: AppState::new(eguiCtx)
    AppState->>Fonts: Load bundled fonts
    Fonts-->>AppState: FontDefinitions
    AppState->>eguiCtx: set_fonts(FontDefinitions)
Loading

Poem

A rabbit hopped in code today,
Swapped old senders—sent them away!
Now egui wakes on every ping,
Fonts from afar make UIs sing.
Developer mode is tucked from sight,
Animations dance just right.
🐇 Hooray for code that feels so light!


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lklimek lklimek requested a review from Copilot June 10, 2025 11:40
@lklimek
Copy link
Copy Markdown
Contributor Author

lklimek commented Jun 10, 2025

@coderabbitai review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request changes the UI repaint behavior by triggering repaints only when necessary, instead of using a fixed 50 ms interval, and refactors several channel-related APIs and internal visibility for easier testing and library integration.

  • Updated all instances of tokio::sync::mpsc sender to use crate::utils::egui_mpsc::SenderAsync.
  • Changed the visibility of several enums and functions to support the library structure and testing requirements.
  • Adjusted the app’s channel creation and UI repaint logic accordingly.

Reviewed Changes

Copilot reviewed 66 out of 66 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/backend_task/* Replaced mpsc::Sender with SenderAsync for task result channels.
src/backend_task/identity/* Updated channel types to SenderAsync.
src/backend_task/contested_names/* Updated channel types and changed enum visibility from pub(crate) to pub.
src/app.rs Modified channel initialization, removed timer-based UI repaint, and changed function visibility for backend tasks.
Cargo.toml Added dependency egui_kittest for additional testing support.
Comments suppressed due to low confidence (3)

src/app.rs:473

  • The visibility of handle_backend_task was changed from public to private. Confirm that this change is intentional and that no external modules rely on this function.
fn handle_backend_task(&self, task: BackendTask) {

src/app.rs:488

  • The change from public to private for handle_backend_tasks might affect external usage. Verify that altering its visibility will not impact modules that expect these functions to be public.
fn handle_backend_tasks(&self, tasks: Vec<BackendTask>, mode: BackendTasksExecutionMode) {

src/backend_task/contested_names/mod.rs:17

  • Changing the enum visibility from pub(crate) to pub may unintentionally expose internal details. Consider whether this change aligns with your intended API design and encapsulation strategy.
pub enum ContestedResourceTask {

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 10, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
src/main.rs (1)

1-1: Consider explicit imports instead of glob import.

While glob imports might be convenient, they can make it harder to track symbol origins and may lead to namespace pollution. Consider importing only the specific items needed.

src/bundled.rs (1)

48-177: Consider error handling and performance implications of bundled fonts.

The fonts() function effectively loads comprehensive international font support. However, consider the following:

  1. Performance: Loading all font variants at startup may impact application launch time. Consider lazy loading for less commonly used scripts.
  2. Error handling: While the function signature returns a Result, no actual error cases are handled within the implementation.
  3. Bundle size: Multiple font files will significantly increase the binary size.

Consider this optimization to conditionally load fonts:

+pub fn fonts_with_options(load_all_scripts: bool) -> Result<egui::FontDefinitions, Box<dyn std::error::Error>> {
+    let mut fonts = FontDefinitions::default();
+    
+    // Always load basic fonts
+    fonts.font_data.insert(
+        "noto_sans".to_owned(),
+        FontData::from_static(include_bytes!(
+            "../assets/Fonts/Noto_Sans/static/NotoSans-Light.ttf"
+        )).into(),
+    );
+    
+    if load_all_scripts {
+        // Load additional script fonts only when needed
+        // ... existing font loading code
+    }
+    
+    Ok(fonts)
+}
src/backend_task/tokens/resume_tokens.rs (1)

26-26: Consider removing unused sender parameter.

The sender parameter type change to crate::utils::egui_mpsc::SenderAsync<TaskResult> is consistent with the broader refactor. However, since the parameter is unused (prefixed with _), consider removing it entirely to clean up the method signature.

Apply this diff to remove the unused parameter:

    pub async fn resume_tokens(
        &self,
        actor_identity: &QualifiedIdentity,
        data_contract: Arc<DataContract>,
        token_position: u16,
        signing_key: IdentityPublicKey,
        public_note: Option<String>,
        group_info: Option<GroupStateTransitionInfoStatus>,
        sdk: &Sdk,
-        _sender: crate::utils::egui_mpsc::SenderAsync<TaskResult>,
    ) -> Result<BackendTaskSuccessResult, String> {

Alternatively, if the parameter is kept for API consistency across backend task methods, the current approach is acceptable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f2bcc3 and d2b7fab.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • icons/dash.png is excluded by !**/*.png
📒 Files selected for processing (64)
  • Cargo.toml (1 hunks)
  • src/app.rs (8 hunks)
  • src/backend_task/contested_names/mod.rs (2 hunks)
  • src/backend_task/contested_names/query_dpns_contested_resources.rs (1 hunks)
  • src/backend_task/contested_names/query_dpns_vote_contenders.rs (1 hunks)
  • src/backend_task/contested_names/query_ending_times.rs (1 hunks)
  • src/backend_task/contested_names/vote_on_dpns_name.rs (1 hunks)
  • src/backend_task/contract.rs (2 hunks)
  • src/backend_task/core/mod.rs (2 hunks)
  • src/backend_task/document.rs (1 hunks)
  • src/backend_task/identity/mod.rs (2 hunks)
  • src/backend_task/identity/refresh_identity.rs (1 hunks)
  • src/backend_task/identity/refresh_loaded_identities_dpns_names.rs (1 hunks)
  • src/backend_task/identity/register_identity.rs (1 hunks)
  • src/backend_task/identity/top_up_identity.rs (1 hunks)
  • src/backend_task/mod.rs (6 hunks)
  • src/backend_task/register_contract.rs (2 hunks)
  • src/backend_task/system_task/mod.rs (1 hunks)
  • src/backend_task/tokens/burn_tokens.rs (1 hunks)
  • src/backend_task/tokens/destroy_frozen_funds.rs (1 hunks)
  • src/backend_task/tokens/freeze_tokens.rs (1 hunks)
  • src/backend_task/tokens/mint_tokens.rs (1 hunks)
  • src/backend_task/tokens/mod.rs (2 hunks)
  • src/backend_task/tokens/pause_tokens.rs (1 hunks)
  • src/backend_task/tokens/purchase_tokens.rs (1 hunks)
  • src/backend_task/tokens/query_my_token_balances.rs (2 hunks)
  • src/backend_task/tokens/query_token_pricing.rs (1 hunks)
  • src/backend_task/tokens/resume_tokens.rs (1 hunks)
  • src/backend_task/tokens/set_token_price.rs (1 hunks)
  • src/backend_task/tokens/transfer_tokens.rs (1 hunks)
  • src/backend_task/tokens/unfreeze_tokens.rs (1 hunks)
  • src/backend_task/update_data_contract.rs (2 hunks)
  • src/bundled.rs (2 hunks)
  • src/components/core_zmq_listener.rs (3 hunks)
  • src/context.rs (5 hunks)
  • src/lib.rs (1 hunks)
  • src/main.rs (2 hunks)
  • src/ui/components/entropy_grid.rs (1 hunks)
  • src/ui/components/left_panel.rs (2 hunks)
  • src/ui/components/styled.rs (6 hunks)
  • src/ui/components/top_panel.rs (1 hunks)
  • src/ui/helpers.rs (1 hunks)
  • src/ui/identities/transfer_screen.rs (1 hunks)
  • src/ui/identities/withdraw_screen.rs (3 hunks)
  • src/ui/network_chooser_screen.rs (2 hunks)
  • src/ui/tokens/burn_tokens_screen.rs (2 hunks)
  • src/ui/tokens/claim_tokens_screen.rs (1 hunks)
  • src/ui/tokens/destroy_frozen_funds_screen.rs (2 hunks)
  • src/ui/tokens/direct_token_purchase_screen.rs (1 hunks)
  • src/ui/tokens/freeze_tokens_screen.rs (2 hunks)
  • src/ui/tokens/mint_tokens_screen.rs (3 hunks)
  • src/ui/tokens/pause_tokens_screen.rs (2 hunks)
  • src/ui/tokens/resume_tokens_screen.rs (2 hunks)
  • src/ui/tokens/set_token_price_screen.rs (1 hunks)
  • src/ui/tokens/tokens_screen/groups.rs (2 hunks)
  • src/ui/tokens/tokens_screen/mod.rs (1 hunks)
  • src/ui/tokens/tokens_screen/my_tokens.rs (2 hunks)
  • src/ui/tokens/transfer_tokens_screen.rs (1 hunks)
  • src/ui/tokens/unfreeze_tokens_screen.rs (2 hunks)
  • src/ui/tokens/update_token_config.rs (2 hunks)
  • src/utils/egui_mpsc.rs (1 hunks)
  • src/utils/mod.rs (1 hunks)
  • tests/kittest/main.rs (1 hunks)
  • tests/kittest/startup.rs (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (13)
tests/kittest/startup.rs (1)
src/app.rs (1)
  • new (143-445)
src/backend_task/identity/register_identity.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/update_data_contract.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/register_contract.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/identity/top_up_identity.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/identity/mod.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/contested_names/query_dpns_contested_resources.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/components/core_zmq_listener.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/identity/refresh_identity.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/tokens/query_my_token_balances.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/backend_task/contested_names/vote_on_dpns_name.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
src/utils/egui_mpsc.rs (1)
src/app.rs (1)
  • new (143-445)
src/backend_task/mod.rs (1)
src/utils/egui_mpsc.rs (2)
  • sender (37-39)
  • sender (100-102)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Clippy
🔇 Additional comments (102)
src/utils/mod.rs (1)

1-1: LGTM - Core module for egui-aware message passing.

This module declaration correctly exposes the new egui_mpsc functionality that enables "repaint UI only when needed" as described in the PR objectives.

tests/kittest/main.rs (1)

1-1: LGTM - Proper test module structure.

The startup module declaration correctly establishes the test infrastructure for egui_kittest, supporting the PR's goal of easier testing.

Cargo.toml (1)

70-70: LGTM - Appropriate test dependency.

The egui_kittest dependency is correctly configured with matching version (0.31.1) and appropriate eframe feature for testing egui applications.

src/backend_task/document.rs (1)

32-32: LGTM - Visibility change supports library refactoring.

Changing the DocumentTask enum visibility to pub aligns with the PR objective of moving logic into a library, making this enum accessible outside the crate.

src/ui/components/entropy_grid.rs (1)

9-14: LGTM - Standard Default implementation.

The Default trait implementation correctly delegates to Self::new(), following standard Rust patterns and improving API ergonomics for contexts requiring default values.

src/ui/components/top_panel.rs (1)

139-139: LGTM! Excellent implementation of centralized animation repaint control.

This change successfully delegates repaint requests to AppContext, enabling conditional animation repaints and addressing the continuous repaint loop issue mentioned in the PR objectives.

src/ui/tokens/unfreeze_tokens_screen.rs (2)

415-415: Good encapsulation improvement.

Replacing direct atomic access with the is_developer_mode() method improves code maintainability and provides better abstraction for developer mode state management.


543-543: Consistent implementation of developer mode encapsulation.

This change maintains consistency with the encapsulation pattern established throughout the codebase.

src/ui/tokens/direct_token_purchase_screen.rs (1)

391-391: Consistent developer mode encapsulation.

This change follows the established pattern of replacing direct atomic access with the encapsulated is_developer_mode() method, improving code consistency and maintainability.

src/backend_task/core/mod.rs (1)

15-15: Verify the necessity of making these enums public.

The visibility change from pub(crate) to pub makes these enums accessible outside the crate. Please confirm this is intentional and necessary for the modularization efforts mentioned in the PR summary.

Does the library separation require these enums to be publicly accessible, or could they remain crate-private?

Also applies to: 41-41

src/ui/helpers.rs (1)

201-201: Excellent completion of developer mode encapsulation.

This change completes the consistent pattern of replacing direct atomic access with the is_developer_mode() method throughout the UI codebase, improving encapsulation and maintainability.

src/ui/tokens/set_token_price_screen.rs (1)

723-723: LGTM: Clean encapsulation of developer mode access.

The change from direct atomic field access to the is_developer_mode() method properly encapsulates the developer mode state while maintaining identical functionality.

src/ui/tokens/freeze_tokens_screen.rs (2)

416-416: LGTM: Consistent developer mode encapsulation.

The refactor from direct atomic access to the is_developer_mode() method aligns with the broader encapsulation improvements across the UI layer.


544-544: LGTM: Proper encapsulation pattern applied consistently.

This change follows the same encapsulation pattern used throughout the UI refactor, replacing direct atomic field access with a clean method interface.

src/ui/tokens/transfer_tokens_screen.rs (1)

350-350: LGTM: Consistent application of developer mode encapsulation.

The change maintains the existing conditional logic while properly encapsulating developer mode access through the new method interface.

src/backend_task/tokens/freeze_tokens.rs (1)

27-27: LGTM: Transition to egui-aware async channels.

The switch from tokio::sync::mpsc::Sender to SenderAsync supports the PR's core objective of integrating UI repaint triggers with async message passing, eliminating inefficient continuous repaints.

src/backend_task/tokens/transfer_tokens.rs (1)

30-30: LGTM: Consistent async channel refactor.

The transition to SenderAsync maintains interface consistency across backend tasks and enables egui-integrated repaint triggering when the sender is utilized.

src/ui/tokens/tokens_screen/mod.rs (1)

1197-1197: LGTM: Good encapsulation improvement.

The change from direct atomic access to using the is_developer_mode() accessor method improves encapsulation and aligns with the broader architectural improvements in this PR. This provides a cleaner API and allows for future changes to the internal implementation without affecting calling code.

src/backend_task/tokens/purchase_tokens.rs (1)

27-27: LGTM: Consistent sender type refactor

The replacement of tokio::sync::mpsc::Sender<TaskResult> with SenderAsync<TaskResult> aligns with the broader refactor to integrate egui-aware message passing. Since the parameter is unused in this method, the change maintains existing functionality while ensuring type consistency across backend tasks.

src/backend_task/tokens/mint_tokens.rs (1)

31-31: LGTM: Consistent with backend task refactor pattern

The sender parameter type change maintains consistency with the broader refactor to use egui-aware message passing. The functional behavior remains unchanged since the parameter is unused.

tests/kittest/startup.rs (1)

4-17: LGTM: Well-implemented startup smoke test

This test provides valuable coverage for the app initialization lifecycle using the appropriate egui_kittest framework. The configuration choices are sound:

  • Disabling animations ensures consistent test behavior
  • Setting a fixed window size provides a predictable rendering context
  • Running one frame is sufficient to catch basic startup issues

This complements the broader refactoring by providing automated verification of app startup behavior.

src/ui/identities/transfer_screen.rs (1)

284-284: LGTM: Excellent encapsulation of developer mode access

The replacement of direct atomic field access with the is_developer_mode() method improves code maintainability by:

  • Hiding implementation details of developer mode storage
  • Providing a cleaner, more semantic API
  • Enabling future changes to developer mode handling without affecting callers

This is a textbook example of good encapsulation practice.

src/ui/tokens/tokens_screen/my_tokens.rs (1)

145-145: LGTM: Consistent application of developer mode encapsulation

Both instances correctly replace direct atomic access with the encapsulated is_developer_mode() method. The consistent application across multiple locations in the same file demonstrates a well-coordinated refactor that improves code maintainability while preserving existing functionality.

Also applies to: 193-193

src/ui/tokens/resume_tokens_screen.rs (2)

378-378: LGTM: Improved encapsulation of developer mode access.

The change from direct atomic access to method call improves code maintainability and follows good encapsulation practices.


487-487: LGTM: Consistent developer mode encapsulation.

Good consistency with the encapsulation pattern applied throughout the file.

src/ui/tokens/burn_tokens_screen.rs (2)

412-412: LGTM: Consistent with developer mode encapsulation refactor.

The change aligns with the systematic refactor to encapsulate developer mode access across UI modules.


551-553: LGTM: Maintains consistency in developer mode access pattern.

The encapsulation change is correctly applied to the button visibility logic while preserving the original conditional behavior.

src/ui/tokens/update_token_config.rs (2)

781-781: LGTM: Proper encapsulation in complex conditional logic.

The developer mode encapsulation is correctly applied even within compound conditional expressions.


1054-1054: LGTM: Consistent developer mode encapsulation pattern.

The systematic application of the encapsulation refactor continues to be consistent across all usage sites.

src/backend_task/contested_names/query_dpns_vote_contenders.rs (1)

20-20: LGTM: Key change supporting egui-aware messaging system.

This change from tokio::sync::mpsc::Sender to SenderAsync is central to the PR's objective of fixing UI repaint efficiency by implementing egui-aware asynchronous messaging.

src/ui/tokens/claim_tokens_screen.rs (1)

305-305: LGTM: Good encapsulation of developer mode access.

The change from direct atomic access to a method call improves maintainability and consistency with the broader refactoring effort.

src/backend_task/tokens/unfreeze_tokens.rs (1)

27-27: LGTM: Improved UI integration with egui-aware sender.

The change to SenderAsync<TaskResult> aligns with the PR objective to optimize UI repaint behavior by integrating backend task communication with egui's repaint system.

src/ui/tokens/mint_tokens_screen.rs (1)

451-451: LGTM: Consistent encapsulation of developer mode access.

All three changes properly replace direct atomic access with the new method call, maintaining consistent behavior while improving code organization and maintainability.

Also applies to: 553-553, 616-616

src/ui/tokens/tokens_screen/groups.rs (1)

155-155: LGTM: Consistent developer mode encapsulation.

Both changes properly replace direct atomic access with the encapsulated method call, maintaining the same conditional logic while improving code consistency.

Also applies to: 179-179

src/backend_task/identity/register_identity.rs (1)

109-109: LGTM: Consistent adoption of egui-aware sender type.

The change to SenderAsync<TaskResult> is consistent with the broader architectural refactoring to integrate backend task communication with egui's repaint system, supporting the PR's UI optimization goals.

src/ui/tokens/pause_tokens_screen.rs (2)

378-385: LGTM: Proper encapsulation of developer mode check.

The change from direct atomic access to the encapsulated is_developer_mode() method improves code consistency and follows the broader refactor pattern. The logic for determining key availability remains unchanged.


487-489: LGTM: Consistent developer mode check for button visibility.

The encapsulated method call maintains the same functionality while improving code organization. The button visibility logic correctly filters out "Test" mode buttons unless in developer mode.

src/ui/components/left_panel.rs (3)

115-121: LGTM: Improved button interaction with hover cursor.

Good UX improvement to store the button response and add cursor icon on hover. This enhances user experience by providing visual feedback for interactive elements.


125-125: LGTM: Updated GradientButton constructor to accept AppContext.

The signature change aligns with the broader refactor where UI components now receive AppContext for animation and repaint functionality. This enables better integration with the event-driven repaint system.


151-151: LGTM: Consistent developer mode encapsulation.

The change from direct atomic access to the encapsulated method call maintains functionality while improving code organization and consistency across the codebase.

src/ui/identities/withdraw_screen.rs (3)

120-120: LGTM: Consistent developer mode encapsulation for address input.

The encapsulated method call maintains the same conditional logic for showing withdrawal address input while improving code consistency with the broader refactor.


169-169: LGTM: Proper developer mode check in confirmation popup.

The change maintains the same logic for handling masternode payout address scenarios while using the encapsulated method for developer mode checking.


316-316: LGTM: Consistent key availability check with encapsulation.

The developer mode check for determining key availability now uses the encapsulated method, maintaining functionality while improving code organization.

src/backend_task/contested_names/query_ending_times.rs (1)

17-17: LGTM: Updated to egui-aware async sender type.

The change from tokio::sync::mpsc::Sender<TaskResult> to crate::utils::egui_mpsc::SenderAsync<TaskResult> aligns with the PR's objective to integrate async task communication with egui's repaint system. This enables automatic UI repaint requests when backend tasks complete.

Note: The parameter is currently unused (_sender), but this is consistent with the method signature requirements and may be utilized in future implementations.

src/ui/network_chooser_screen.rs (2)

64-64: LGTM: Consistent developer mode reading with encapsulation.

The change from direct atomic access to the encapsulated is_developer_mode() method maintains functionality while improving code consistency with the broader refactor pattern.


352-368: LGTM: Proper developer mode updates across all network contexts.

The change from direct atomic stores to the encapsulated enable_developer_mode() method correctly updates developer mode settings for all AppContext instances (mainnet, testnet, devnet, local). This ensures consistency across all network configurations.

src/backend_task/tokens/query_token_pricing.rs (1)

13-13: LGTM: Parameter type updated consistently with the refactor.

The change from tokio::sync::mpsc::Sender<TaskResult> to crate::utils::egui_mpsc::SenderAsync<TaskResult> is consistent with the broader refactor to use egui-aware senders. The underscore prefix correctly indicates this parameter is unused in the function.

src/backend_task/contested_names/query_dpns_contested_resources.rs (2)

19-19: LGTM: Sender parameter type updated for egui integration.

The parameter type change from mpsc::Sender<TaskResult> to crate::utils::egui_mpsc::SenderAsync<TaskResult> is consistent with the refactor to integrate message sending with egui's repaint system. The sender is actively used throughout the function for progress updates and result communication.


149-255: Sender usage patterns are correct.

All sender.send() calls are properly awaited and include appropriate error handling. The mix of map_err() and expect() for error handling is acceptable, with expect() used for internal communications where failures would indicate programming errors.

src/ui/tokens/destroy_frozen_funds_screen.rs (2)

436-436: LGTM: Improved encapsulation of developer mode access.

The change from self.app_context.developer_mode.load(Ordering::Relaxed) to self.app_context.is_developer_mode() improves encapsulation by hiding atomic implementation details behind a clean method interface. This makes the code more maintainable and consistent with the broader refactor.


563-563: LGTM: Consistent developer mode access pattern.

Same improvement as line 436 - replacing direct atomic access with the encapsulated is_developer_mode() method call for better code organization and maintainability.

src/backend_task/identity/top_up_identity.rs (2)

25-25: LGTM: Parameter type updated for egui integration.

The sender parameter type change is consistent with the systematic refactor to use egui-aware senders throughout the backend task modules.


335-340: Sender usage is correct.

The sender.send() call is properly awaited and includes appropriate error handling with map_err() to convert the send error to a string.

src/backend_task/identity/refresh_loaded_identities_dpns_names.rs (2)

14-14: LGTM: Consistent parameter type update.

The sender parameter type change aligns with the systematic refactor to use egui-aware senders across all backend task modules.


78-83: Proper sender usage with error handling.

The sender.send() call is correctly awaited and includes comprehensive error handling that formats the error message appropriately for the context.

src/backend_task/tokens/set_token_price.rs (1)

28-28: LGTM!

The sender type change to SenderAsync<TaskResult> is consistent with the broader refactor. The parameter remains correctly prefixed with _ since it's unused in this method.

src/backend_task/tokens/mod.rs (2)

61-61: Visibility change aligns with library refactoring.

Making TokenTask public is appropriate for the library refactoring mentioned in the PR objectives, allowing external usage of these task types.


213-213: Consistent sender type update.

The change to SenderAsync<TaskResult> properly integrates with the egui-aware message passing system, ensuring UI repaints are triggered only when tasks send results.

src/backend_task/identity/refresh_identity.rs (1)

16-16: Proper integration with egui repaint system.

The SenderAsync type ensures that the UI will repaint when the refresh message is sent after identity update, improving UI responsiveness.

src/main.rs (1)

24-40: Clean modularization of startup logic.

The extraction of initialization logic into a separate start function and moving font loading elsewhere improves code organization and aligns with the library refactoring goals.

src/backend_task/system_task/mod.rs (1)

7-7: Consistent refactoring of task visibility and sender type.

Both changes align with the systematic refactor across all backend task modules - making task enums public for library usage and adopting the egui-aware SenderAsync type.

Also applies to: 15-15

src/backend_task/contract.rs (2)

31-31: LGTM: Improved visibility for external crate usage.

Making ContractTask public enhances the API accessibility, aligning with the library modularization goals.


46-46: LGTM: Consistent migration to egui-aware sender.

The migration from tokio::sync::mpsc::Sender<TaskResult> to crate::utils::egui_mpsc::SenderAsync<TaskResult> is correctly implemented. The new type maintains the same async interface while integrating UI repaint requests, supporting the PR's objective to optimize UI repainting.

src/backend_task/update_data_contract.rs (2)

29-29: LGTM: Clean import management.

Correctly retaining only the needed tokio::time::sleep import while removing the no-longer-needed tokio::sync::mpsc import.


62-62: LGTM: Consistent sender type migration.

The migration to crate::utils::egui_mpsc::SenderAsync<TaskResult> is correctly implemented, maintaining the async interface while enabling UI repaint integration.

src/backend_task/identity/mod.rs (2)

248-248: LGTM: Enhanced API accessibility.

Making IdentityTask public improves external crate accessibility, consistent with the library modularization approach.


442-442: LGTM: Proper sender type migration.

The migration to crate::utils::egui_mpsc::SenderAsync<TaskResult> is correctly implemented and will be properly threaded through to the various identity task methods.

src/lib.rs (1)

1-15: LGTM: Well-structured library modularization.

The comprehensive module structure effectively organizes the codebase into logical components, supporting the PR's goal of moving logic into a library for easier testing. The public visibility enables external crate usage while maintaining clear separation of concerns.

src/backend_task/register_contract.rs (2)

8-8: LGTM: Appropriate import management.

Correctly maintaining only the necessary tokio::time::sleep import while removing the no-longer-needed tokio::sync::mpsc import.


30-30: LGTM: Consistent egui-aware sender adoption.

The migration to crate::utils::egui_mpsc::SenderAsync<TaskResult> follows the established pattern and correctly maintains the async interface while enabling UI repaint optimization.

src/backend_task/contested_names/mod.rs (2)

17-17: LGTM: Making enum public for library modularity.

The visibility change from pub(crate) to pub aligns with the PR objective of refactoring the codebase to move logic into a library, allowing external access to this enum.


41-41:

Details

✅ Verification successful

Verify consistency of egui-aware sender usage across the codebase.

The sender parameter type change to crate::utils::egui_mpsc::SenderAsync<TaskResult> correctly integrates with the new egui-aware message passing system to trigger UI repaints only when needed.

Run the following script to verify all backend task methods use the new sender type consistently:


🏁 Script executed:

#!/bin/bash
# Description: Verify all backend task methods use the new egui-aware sender type.
# Expected: All async task methods should use SenderAsync<TaskResult>.

# Search for any remaining usage of tokio::sync::mpsc::Sender<TaskResult>
echo "=== Checking for old tokio sender usage ==="
rg -A 3 "tokio::sync::mpsc::Sender<TaskResult>"

# Search for new egui-aware sender usage
echo "=== Checking new egui-aware sender usage ==="
rg -A 3 "crate::utils::egui_mpsc::SenderAsync<TaskResult>"

# Search for potential missed conversions in backend task files
echo "=== Checking for potential missed conversions ==="
rg -A 5 "async.*sender.*TaskResult" src/backend_task/

Length of output: 11553


All backend tasks consistently use the egui-aware sender

Verification confirms that there are no remaining uses of tokio::sync::mpsc::Sender<TaskResult> and every async method in src/backend_task/ now declares its sender as crate::utils::egui_mpsc::SenderAsync<TaskResult>. No further changes needed.

src/components/core_zmq_listener.rs (1)

63-63: LGTM: Consistent integration with egui-aware synchronous channels.

The change to crate::utils::egui_mpsc::SenderSync<(ZMQMessage, Network)> correctly integrates the ZMQ listener with the egui repaint system. Using SenderSync (rather than SenderAsync) is appropriate for this synchronous context where the listener runs in a background thread.

Both platform-specific implementations (#[cfg] blocks) are consistently updated, ensuring cross-platform compatibility.

Also applies to: 285-285

src/backend_task/contested_names/vote_on_dpns_name.rs (1)

26-26: LGTM: Consistent migration to egui-aware async channels.

The sender parameter type change to crate::utils::egui_mpsc::SenderAsync<TaskResult> is consistent with the broader refactor across backend task modules. The existing usage of sender.send(TaskResult::Refresh).await on lines 30-33 remains compatible with the new wrapper type.

src/backend_task/tokens/burn_tokens.rs (1)

30-30: LGTM: Consistent with egui-aware sender refactoring.

The parameter type change from tokio::sync::mpsc::Sender<TaskResult> to crate::utils::egui_mpsc::SenderAsync<TaskResult> aligns with the PR's objective to use egui-aware message passing. Since the parameter is unused (indicated by the _ prefix), this change is safe and maintains API compatibility.

src/backend_task/tokens/query_my_token_balances.rs (1)

18-18: LGTM: Proper integration of egui-aware senders for UI refresh.

The parameter type changes to crate::utils::egui_mpsc::SenderAsync<TaskResult> are excellent here because these functions actively use the sender to send TaskResult::Refresh messages (lines 76-79, 127-130). With the new egui-aware senders, these refresh messages will automatically trigger UI repaints, ensuring the UI updates immediately after successful database operations.

Also applies to: 98-98

src/backend_task/tokens/pause_tokens.rs (1)

26-26: LGTM: Consistent parameter type update.

The change from tokio::sync::mpsc::Sender<TaskResult> to crate::utils::egui_mpsc::SenderAsync<TaskResult> is consistent with the broader refactoring. The unused parameter (indicated by _ prefix) makes this a safe change.

src/context.rs (6)

43-43: Good choice for animation timing.

The 100ms refresh interval for ANIMATION_REFRESH_TIME provides smooth animations while avoiding excessive CPU usage. This strikes a good balance for UI responsiveness.


48-48: Excellent encapsulation improvement.

Making developer_mode private and adding the animate field with proper encapsulation improves the API design. This prevents direct access to internal state and ensures animation control is properly coordinated with developer mode.

Also applies to: 71-71


147-154: Smart inverse relationship between developer mode and animations.

The logic that disables animations when developer mode is enabled is well-designed for debugging scenarios. The logging message clearly explains the behavior, which will help developers understand why animations are disabled during development.


186-194: Well-designed animation control methods.

The enable_animations and enable_developer_mode methods provide clean APIs for controlling these related states. The inverse relationship between developer mode and animations is properly maintained in enable_developer_mode.


203-208: Efficient conditional repaint mechanism.

The repaint_animation method efficiently checks the animation flag before requesting repaints, preventing unnecessary repaint requests when animations are disabled. This aligns perfectly with the PR's goal of optimizing UI repaint behavior.


215-215: Proper use of encapsulated accessor method.

Replacing direct atomic load with the is_developer_mode() accessor method maintains consistency with the new encapsulation pattern.

src/utils/egui_mpsc.rs (9)

7-10: Well-designed wrapper structure.

The SenderAsync<T> struct cleanly wraps the tokio sender with an egui context. The generic type parameter and field organization are appropriate for this use case.


19-25: Correct async send implementation with repaint triggering.

The send method properly delegates to the underlying sender and only triggers a repaint on successful sends. This prevents unnecessary repaints when the channel is closed or full, which is exactly the behavior we want for efficient UI updates.


28-34: Proper try_send implementation.

The try_send method correctly implements non-blocking send with the same repaint-on-success pattern. This provides both blocking and non-blocking send options while maintaining consistent repaint behavior.


37-44: Good utility methods for sender access.

The sender() method provides access to the underlying sender when needed, and is_closed() properly delegates to check channel status. These utility methods maintain the wrapper's transparency while providing necessary functionality.


47-54: Correct Clone implementation.

The Clone implementation properly clones both the sender (which is cheap for mpsc senders) and the egui context, maintaining the wrapper's functionality across clones.


55-64: Excellent trait design for channel conversion.

The EguiMpscAsync trait provides a clean API for converting raw tokio channels into egui-aware channels. The with_egui_ctx method name is descriptive and the implementation correctly wraps only the sender while leaving the receiver unchanged.


66-75: Consistent synchronous counterpart.

The EguiMpscSync trait mirrors the async version for standard library channels, providing consistency across both async and sync use cases. This design allows the application to use egui-aware channels throughout the codebase regardless of the underlying channel type.


79-97: Well-implemented synchronous sender wrapper.

The SenderSync<T> implementation mirrors the async version with proper error handling and repaint triggering. The synchronous send method maintains the same pattern of only triggering repaints on successful sends.


105-112: Consistent Clone implementation for sync wrapper.

The Clone implementation for SenderSync maintains the same pattern as the async version, ensuring consistent behavior across both wrapper types.

src/app.rs (4)

26-26: Good architectural change for event-driven UI updates.

The migration from tokio::sync::mpsc::Sender to egui_mpsc::SenderAsync is a solid approach to replace the inefficient 50ms repaint timer with event-driven updates. This change aligns perfectly with the PR's objective to repaint UI only when needed.

Also applies to: 72-72


143-143: Breaking API change: new constructor requires egui::Context.

This is a necessary breaking change to support the new event-driven repaint mechanism. The egui context is required to associate channels with the UI for automatic repaint triggers.


447-461: Well-designed animation control API.

The with_animations method provides a clean builder pattern for controlling animations globally across all network contexts. This aligns perfectly with the PR objective to add a flag for disabling animated UI elements.


473-473: Good encapsulation improvement.

Making handle_backend_task and handle_backend_tasks private properly encapsulates internal task handling logic.

Also applies to: 488-488

src/backend_task/mod.rs (3)

13-13: Consistent migration to egui-aware channels.

The import change from tokio::sync::mpsc to crate::utils::egui_mpsc::SenderAsync is consistent with the architectural changes in app.rs and supports the event-driven UI update mechanism.


97-97: Consistent sender type updates across all methods.

All backend task methods have been consistently updated to use SenderAsync<TaskResult> instead of the tokio sender. The implementation logic remains unchanged, ensuring backward compatibility while enabling the new repaint mechanism.

Also applies to: 113-113, 131-131


44-44:

Details

❓ Verification inconclusive

Verify the necessity of public enum exposure.

The visibility change from pub(crate) to pub for BackendTask and BackendTaskSuccessResult exposes these enums to external crates. This aligns with the PR objective of moving logic into a library, but please confirm this is intentional and these types are meant to be part of the public API.

Also applies to: 58-58


🏁 Script executed:

#!/bin/bash
# Description: Check if these enums are used in public API or tests
# Look for usage in lib.rs or public modules
fd -e rs | xargs rg "BackendTask|BackendTaskSuccessResult" -B 2 -A 2 | grep -E "(pub\s+(fn|mod)|#\[test\])"

Length of output: 232


Confirm public visibility for BackendTask

I verified that BackendTaskSuccessResult is returned by the public function wipe_devnet, so making it pub is necessary. However, I didn’t find any public APIs or tests exposing BackendTask.

• If BackendTask is not intended for external use, please revert its visibility back to pub(crate).
• Otherwise, confirm it’s part of your public API and keep it pub.

src/ui/components/styled.rs (3)

14-14: Good API surface reduction.

Restricting ButtonVariant, StyledButton, and ButtonSize to pub(crate) reduces the public API surface, which is good practice if these components are only used internally. This change improves encapsulation and reduces maintenance burden.

Also applies to: 22-22, 32-32


125-130: Good addition of Default trait.

Adding a Default implementation for StyledCard improves ergonomics and follows Rust best practices. The implementation correctly delegates to the existing new() method.


217-217: Excellent implementation of controlled animation repaints.

The GradientButton now properly delegates repaint requests to AppContext::repaint_animation, which can conditionally trigger repaints based on the animation settings. This is a key improvement that addresses the PR's objective of eliminating unnecessary repaints while maintaining smooth animations when enabled.

Also applies to: 221-221, 260-260

Comment thread src/backend_task/tokens/destroy_frozen_funds.rs
Comment thread src/main.rs Outdated
Comment thread src/app.rs
Comment on lines +174 to +176
// load fonts
ctx.set_fonts(crate::bundled::fonts().expect("failed to load fonts"));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify error handling for font loading.

The font loading uses expect("failed to load fonts") which will panic if fonts fail to load. Consider whether this should be a recoverable error or if a panic is appropriate for missing fonts.


🏁 Script executed:

#!/bin/bash
# Description: Check the bundled fonts module implementation
ast-grep --pattern 'pub fn fonts() -> $_' src/bundled.rs

Length of output: 58


🏁 Script executed:

#!/bin/bash
# Search for the fonts function signature across all Rust source files
rg -n "fn fonts" -g "*.rs"

Length of output: 124


Handle potential font-loading errors without panicking

The fonts() function returns a Result<egui::FontDefinitions, Box<dyn std::error::Error>>. Calling it with .expect("failed to load fonts") will abort the application on failure. Instead, decide whether missing fonts should:

  • Be treated as a recoverable error, with a fallback to default fonts or a logged warning
  • Or be propagated as an error from main

For example, to log and use defaults:

// src/app.rs:174
match crate::bundled::fonts() {
    Ok(fonts) => ctx.set_fonts(fonts),
    Err(err) => {
        log::error!("Failed to load fonts: {}", err);
        ctx.set_fonts(egui::FontDefinitions::default());
    }
}

Or, to bubble up the error:

// Change your `main` signature to return Result<(), Box<dyn Error>>
fn main() -> Result<(), Box<dyn std::error::Error>> {
    // …
    let fonts = crate::bundled::fonts()?;
    ctx.set_fonts(fonts);
    // …
}

Please update the font-loading call in src/app.rs accordingly.

🤖 Prompt for AI Agents
In src/app.rs around lines 174 to 176, the font loading uses expect which panics
on failure. Replace this with proper error handling by matching on the Result
returned from crate::bundled::fonts(). On Ok, set the fonts as usual; on Err,
either log the error and set default fonts or propagate the error by changing
main to return a Result and using the ? operator. This avoids panics and handles
font loading failures gracefully.

@QuantumExplorer QuantumExplorer merged commit bc44379 into v0.9-dev Jun 26, 2025
3 checks passed
@QuantumExplorer QuantumExplorer deleted the fix/repaint-50ms branch June 26, 2025 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants