Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-address support to "Faucet" button #2533

Open
wants to merge 15 commits into
base: dev
Choose a base branch
from

Conversation

TazzyMeister
Copy link

@TazzyMeister TazzyMeister commented Feb 18, 2025

Remove the faucet button from the coin overview and add it as a button icon in the addresses list

Move references to faucet_button.dart from the details page to the coin address list. Note that you might have to change how the page is called in coin_details.dart to pass the selected address of the coin (rather than defaultAddress)

Summary by CodeRabbit

  • New Features

    • Enhanced faucet interaction for coins that support it—users now experience dynamic feedback when requesting faucet operations.
  • Refactor

    • Streamlined navigation and user interfaces by removing redundant faucet pages from coin details and desktop views, and updating dialogs with a clear close action.
    • Improved coin address screens now support smoother navigation between different functionality options.

Remove the faucet button from the coin overview and add it as a button icon in the addresses list

Move references to faucet_button.dart from the details page to the coin address list. Note that you might have to change how the page is called in coin_details.dart to pass the selected address of the coin (rather than defaultAddress)

NB: Take a branch from dev  and name it add/multi-address-faucet
Copy link

coderabbitai bot commented Feb 18, 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 integrates a new faucet feature managed by a dedicated bloc. A new FaucetBloc is provided in AppBlocRoot to handle faucet events and state transitions. Several new files now define the bloc, events, and states for the faucet feature. Concurrently, faucet-related UI components have been refactored or removed from areas like coin details and associated buttons or pages. Notably, the faucet functionality has shifted from being available in some views to a more centralized bloc-managed approach.

Changes

File(s) Change Summary
lib/bloc/app_bloc_root.dart Added import for FaucetBloc and integrated a new BlocProvider<FaucetBloc> into the MultiBlocProvider.
lib/bloc/faucet_button/…
faucet_button_bloc.dart,
faucet_button_event.dart,
faucet_button_state.dart
Introduced new files defining FaucetBloc, its events (FaucetRequested), and states (FaucetInitial, FaucetLoading, FaucetSuccess, FaucetError), implementing sequential request handling with error management.
lib/views/wallet/coin_details/coin_details.dart Removed handling for CoinPageType.faucet from the _buildContent method.
lib/views/wallet/coin_details/coin_details_info/coin_addresses.dart Updated constructor to include a new required setPageType parameter and conditionally rendered the FaucetButton based on coin.hasFaucet.
lib/views/wallet/coin_details/coin_details_info/coin_details_common_buttons.dart Removed the import and conditional rendering of the faucet button from the desktop layout.
lib/views/wallet/coin_details/coin_details_info/coin_details_info.dart Eliminated the _FaucetButton class and updated widget instantiations to remove faucet-related parameters from the coin details view.
lib/views/wallet/coin_details/coin_page_type.dart Removed the faucet value from the CoinPageType enum.
lib/views/wallet/coin_details/faucet/faucet_button.dart Refactored FaucetButton from a stateless to a stateful widget; updated constructor parameters to require coinAbbr and address and integrated a BlocConsumer for state listening and UI updates.
lib/views/wallet/coin_details/faucet/faucet_page.dart Changed FaucetPage from stateless to stateful, requiring a non-nullable coinAddress and simplifying internal state management by removing bloc dependencies.
lib/views/wallet/coin_details/faucet/faucet_view.dart Updated FaucetView to accept coinAbbr, coinAddress, and onClose instead of an onBackButtonPressed callback; replaced layout components with a dialog and updated corresponding child components.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant FaucetButton
    participant FaucetBloc
    participant FaucetAPI

    User->>FaucetButton: Click button
    FaucetButton->>FaucetBloc: Dispatch FaucetRequested(coinAbbr, address)
    FaucetBloc->>FaucetAPI: Call faucet API with coinAbbr & address
    FaucetAPI-->>FaucetBloc: Return response (success/error)
    FaucetBloc-->>FaucetButton: Emit state (FaucetLoading, then FaucetSuccess/FaucetError)
    FaucetButton->>User: Update UI (e.g., show dialog or error message)
Loading

Suggested labels

enhancement, bug

Suggested reviewers

  • AndrewDelaney
  • smk762
  • ShantanuSharma9873

Poem

I'm a rabbit with a coding beat,
Hopping through changes oh so neat.
Faucet flows now with a rhythmic rhyme,
Blocs and views aligned in time.
In the garden of code I cheer and tap—
Carrots of progress, a delightful rap!
🐇💻


🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 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.

@CharlVS
Copy link
Member

CharlVS commented Mar 6, 2025

@coderabbitai review

Copy link

coderabbitai bot commented Mar 6, 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

@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: 0

🧹 Nitpick comments (7)
lib/views/wallet/coin_details/faucet/faucet_button.dart (4)

29-30: Consider instance-based address tracking instead of static variable.

The static _activeAddress variable can cause issues if multiple FaucetButtons are active simultaneously, as they would overwrite each other's active address. This could lead to unexpected behavior, especially if users interact with multiple buttons in quick succession.

class _FaucetButtonState extends State<FaucetButton> {
-  static String? _activeAddress;
+  bool _isRequesting = false;

Then update the button logic accordingly:

  onPressed: () {
-    if (_activeAddress != null) {
+    if (_isRequesting) {
      return;
    }
-    _activeAddress = widget.address.address;
+    setState(() => _isRequesting = true);
    context.read<FaucetBloc>().add(FaucetRequested(
      coinAbbr: widget.coinAbbr,
      address: widget.address.address,
    ));
  },

And in the listener:

  Future.delayed(Duration(milliseconds: 300), () {
-    _activeAddress = null;
+    if (mounted) setState(() => _isRequesting = false);
  });

36-61: Add visual indication when button is disabled.

The button is functionally disabled when _activeAddress is set, but there's no visual indication to the user. The button should show a disabled state to improve user experience.

child: UiPrimaryButton(
  key: Key('coin-details-faucet-button-${widget.address.address}'),
  height: isMobile ? 24.0 : 32.0,
  backgroundColor: themeData.colorScheme.tertiary,
+ enabled: _activeAddress == null && widget.enabled,
  onPressed: () {
    if (_activeAddress != null) {
      return;
    }
    _activeAddress = widget.address.address;
    context.read<FaucetBloc>().add(FaucetRequested(
      coinAbbr: widget.coinAbbr,
      address: widget.address.address,
    ));
  },

37-40: Improve listenWhen condition for better state management.

The current listenWhen condition only considers the active address, but it should also verify relevant state transitions to avoid unnecessary dialog displays.

listenWhen: (previous, current) {
-  return _activeAddress == widget.address.address;
+  return _activeAddress == widget.address.address && 
+         (current is FaucetLoading || 
+          (previous is FaucetLoading && current is! FaucetLoading));
},

51-55: Add error handling for Future.delayed.

Using a fixed delay to reset state could lead to timing issues. Consider using the FaucetBloc state transitions to manage the button state instead of a timer.

onClose: () {
  Navigator.of(dialogContext).pop();
-  Future.delayed(Duration(milliseconds: 300), () {
-    _activeAddress = null;
-  });
+  // Reset immediately or on next frame to ensure UI consistency
+  WidgetsBinding.instance.addPostFrameCallback((_) {
+    if (mounted) {
+      setState(() {
+        _activeAddress = null;
+      });
+    }
+  });
},
lib/views/wallet/coin_details/faucet/faucet_view.dart (3)

26-46: Consider enhancing dialog accessibility.

The Dialog implementation lacks some accessibility features that would improve usability.

return Dialog(
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
+ insetPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
+ clipBehavior: Clip.antiAliasWithSaveLayer,
  child: Container(
    constraints: const BoxConstraints(maxWidth: 400),
    padding: const EdgeInsets.all(16),
    child: BlocBuilder<FaucetBloc, FaucetState>(
+     buildWhen: (previous, current) => previous != current,
      builder: (context, state) {
        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            _DialogHeader(title: title(state), onClose: onClose),
            _StatesOfPage(
              state: state,
              onClose: onClose,
            ),
          ],
        );
      },
    ),
  ),
);

63-86: Enhance dialog header with better semantics.

The dialog header could be improved with additional semantics for screen readers.

class _DialogHeader extends StatelessWidget {
  final String title;
  final VoidCallback onClose;

  const _DialogHeader({required this.title, required this.onClose});

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: Text(
            title,
            style: Theme.of(context).textTheme.titleLarge,
+           semanticsLabel: title,
          ),
        ),
        IconButton(
          icon: const Icon(Icons.close),
          onPressed: onClose,
+         tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
+         semanticsLabel: MaterialLocalizations.of(context).closeButtonTooltip,
        ),
      ],
    );
  }
}

96-98: Add loading state indicator and cancel option.

The loading state doesn't provide any way for users to cancel an in-progress request, which could be problematic if the request is taking too long.

if (localState is FaucetLoading || localState is FaucetInitial) {
-  return const _Loading();
+  return _Loading(onCancel: onClose);
}

Then update the _Loading class:

class _Loading extends StatelessWidget {
-  const _Loading();
+  final VoidCallback? onCancel;
+  const _Loading({this.onCancel});

  @override
  Widget build(BuildContext context) {
-    return const Column(
+    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
-        SizedBox(height: 28),
-        Center(child: UiSpinner()),
-        SizedBox(height: 28),
+        const SizedBox(height: 28),
+        const Center(child: UiSpinner()),
+        const SizedBox(height: 28),
+        if (onCancel != null)
+          Center(
+            child: TextButton(
+              onPressed: onCancel,
+              child: Text(LocaleKeys.cancel.tr()),
+            ),
+          ),
+        const SizedBox(height: 12),
      ],
    );
  }
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9ce4ef2 and 3ed8386.

📒 Files selected for processing (12)
  • lib/bloc/app_bloc_root.dart (2 hunks)
  • lib/bloc/faucet_button/faucet_button_bloc.dart (1 hunks)
  • lib/bloc/faucet_button/faucet_button_event.dart (1 hunks)
  • lib/bloc/faucet_button/faucet_button_state.dart (1 hunks)
  • lib/views/wallet/coin_details/coin_details.dart (0 hunks)
  • lib/views/wallet/coin_details/coin_details_info/coin_addresses.dart (5 hunks)
  • lib/views/wallet/coin_details/coin_details_info/coin_details_common_buttons.dart (0 hunks)
  • lib/views/wallet/coin_details/coin_details_info/coin_details_info.dart (2 hunks)
  • lib/views/wallet/coin_details/coin_page_type.dart (1 hunks)
  • lib/views/wallet/coin_details/faucet/faucet_button.dart (1 hunks)
  • lib/views/wallet/coin_details/faucet/faucet_page.dart (2 hunks)
  • lib/views/wallet/coin_details/faucet/faucet_view.dart (5 hunks)
💤 Files with no reviewable changes (2)
  • lib/views/wallet/coin_details/coin_details.dart
  • lib/views/wallet/coin_details/coin_details_info/coin_details_common_buttons.dart
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Build Desktop (linux)
  • GitHub Check: Test web-app-macos
  • GitHub Check: Build Desktop (windows)
  • GitHub Check: Build Mobile (Android)
  • GitHub Check: Test web-app-linux-profile
  • GitHub Check: Build Desktop (macos)
  • GitHub Check: validate_code_guidelines
  • GitHub Check: Build Mobile (iOS)
  • GitHub Check: unit_tests
🔇 Additional comments (19)
lib/views/wallet/coin_details/coin_page_type.dart (1)

1-1: Change aligns with the PR objective.

The removal of the faucet value from the CoinPageType enum is consistent with the PR's goal of relocating the faucet button from the coin overview section to the addresses list.

lib/bloc/faucet_button/faucet_button_event.dart (1)

3-21: Well-structured BLoC event implementation.

The event architecture follows good BLoC pattern practices with proper use of:

  • Abstract base class extending Equatable
  • Immutable fields with required parameters
  • Correctly overridden props getter for equality comparison

This structure will support the faucet functionality being moved to the addresses list as described in the PR objectives.

lib/bloc/app_bloc_root.dart (2)

33-33: Appropriate import for the new faucet functionality.

This import supports the integration of the new faucet button BLoC implementation.


308-310: BLoC integration follows established patterns.

The FaucetBloc provider is correctly integrated into the application's state management architecture, using the same pattern as other BLoC providers in the file. This ensures the faucet functionality will be accessible throughout the widget tree.

lib/bloc/faucet_button/faucet_button_state.dart (1)

4-35: Comprehensive state management for faucet operations.

The state architecture is well-implemented with:

  • A clear hierarchy with an abstract base class
  • Distinct states for initial, loading, success and error scenarios
  • Proper use of Equatable for state comparison
  • Appropriate props overrides in states with data

This state management approach will provide good user feedback during faucet operations and handle different outcomes effectively.

lib/views/wallet/coin_details/faucet/faucet_page.dart (2)

4-18: Improved architecture by converting to StatefulWidget

The change from StatelessWidget to StatefulWidget provides better structure for this component, making it more maintainable as it now properly isolates state management.


20-29: Good implementation of state handling

The implementation now directly uses FaucetView with the needed properties, which simplifies the widget hierarchy and removes unnecessary BlocProvider wrapping at this level.

lib/views/wallet/coin_details/coin_details_info/coin_details_info.dart (2)

190-191: Correctly passing setPageType to CoinAddresses

This change enables the address list to handle navigation to the faucet feature, which aligns with moving the faucet functionality from the overview to the addresses list.


294-298: Correctly passing setPageType to CoinAddresses in mobile layout

The changes ensure consistent behavior between desktop and mobile interfaces by passing the same navigation function.

lib/bloc/faucet_button/faucet_button_bloc.dart (3)

1-8: Good imports organization for the new faucet bloc

The imports are well-organized, including all necessary dependencies for the bloc implementation. The sequential import from bloc_concurrency will help prevent race conditions in faucet requests.


9-15: Well-structured FaucetBloc implementation

The bloc implementation follows best practices by:

  1. Storing KomodoDefiSdk as a dependency
  2. Correctly initializing the initial state
  3. Using the sequential transformer to prevent multiple simultaneous requests

16-41: Comprehensive event handling with proper error management

The _onFaucetRequest method:

  1. Correctly checks if already loading to prevent duplicate requests
  2. Properly emits loading state at the beginning
  3. Has comprehensive try/catch error handling
  4. Properly differentiates between API errors and network errors
  5. Uses the addError method to properly log errors with stack traces

This implementation ensures that errors are properly handled and reported to the user with meaningful messages.

lib/views/wallet/coin_details/coin_details_info/coin_addresses.dart (5)

21-22: Added necessary imports for faucet functionality

The imports for the faucet button and page type are required for the new faucet integration in the address list.


28-32: Added required setPageType parameter to CoinAddresses

This parameter addition ensures the component can handle navigation to the faucet page when requested.


198-204: Added required setPageType parameter to AddressCard

Passing the navigation function down to the address card allows each individual address to trigger faucet functionality.


228-238: Well-implemented faucet button in mobile layout

The faucet button is:

  1. Correctly conditionally rendered based on coin.hasFaucet
  2. Properly constrained with appropriate size limits
  3. Correctly receiving the coin abbreviation and address parameters

This implementation properly integrates the faucet functionality into the mobile address list view.


261-271: Well-implemented faucet button in desktop layout

The desktop implementation correctly mirrors the mobile implementation while considering desktop UI requirements. The button is properly positioned in the address row.

lib/views/wallet/coin_details/faucet/faucet_button.dart (1)

13-27: Good conversion to StatefulWidget to handle state changes.

The change from StatelessWidget to StatefulWidget is appropriate for maintaining state during faucet operations. The constructor parameters now properly support multiple addresses, aligning with the PR objective of adding multi-address support.

lib/views/wallet/coin_details/faucet/faucet_view.dart (1)

13-18: Good API redesign for multi-address support.

The constructor parameters now properly include coinAbbr and coinAddress, enabling the faucet to work with any selected address rather than just the default address. This aligns well with the PR objective.

@TazzyMeister TazzyMeister marked this pull request as ready for review March 6, 2025 16:25
@CharlVS
Copy link
Member

CharlVS commented Mar 6, 2025

@coderabbitai review

Copy link

coderabbitai bot commented Mar 6, 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.

Made changes of tracking active address to not use a static variable but rather handle it in the bloc and not in the button.

Made some changes to the UI to show unactive buttons.

Improved state management in Listenerwhen.
@CharlVS CharlVS added the QA Ready for QA Testing label Mar 12, 2025
@CharlVS CharlVS self-requested a review March 12, 2025 11:45
@CharlVS
Copy link
Member

CharlVS commented Mar 12, 2025

@ShantanuSharma9873 Please test that the faucet button works in HD wallet mode for test coins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
QA Ready for QA Testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants